mirror of
https://github.com/curioustorvald/Terrarum-sans-bitmap.git
synced 2026-06-06 05:58:30 +09:00
Compare commits
11 Commits
71ea63b48e
...
39603d897b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39603d897b | ||
|
|
2b1f9a866f | ||
|
|
af1d720ec2 | ||
|
|
8a52fcfb91 | ||
|
|
b82dbecc30 | ||
|
|
2008bbf6dd | ||
|
|
163e3d7b3e | ||
|
|
f26998b641 | ||
|
|
4121648dfc | ||
|
|
30de279a08 | ||
|
|
956599b83f |
BIN
Autokem/autokem.safetensors
LFS
BIN
Autokem/autokem.safetensors
LFS
Binary file not shown.
@@ -46,8 +46,8 @@ Rightmost vertical column (should be 20 px tall) contains the tags. Tags are def
|
||||
W |= Width of the character
|
||||
W |
|
||||
W -'
|
||||
m --Is this character lowheight?
|
||||
K -,
|
||||
K |
|
||||
K |= Tags used by the "Keming Machine"
|
||||
K -'
|
||||
Q ---Compiler Directive (see below)
|
||||
@@ -77,29 +77,32 @@ Up&Down:
|
||||
|
||||
<MSB,Red> SXXXXXXX SYYYYYYY 00000000 <LSB,Blue>
|
||||
|
||||
Each X and Y numbers are Signed 8-Bit Integer.
|
||||
Each X and Y numbers are TWO'S COMPLEMENT Signed 8-Bit Integer.
|
||||
|
||||
X-positive: nudges towards left
|
||||
Y-positive: nudges towards up
|
||||
Y-positive: nudges towards down
|
||||
|
||||
#### Diacritics Anchor Point Encoding
|
||||
|
||||
4 Pixels are further divided as follows:
|
||||
|
||||
| LSB | | Red | Green | Blue |
|
||||
| ------------ | ------------ | ------------ | ------------ | ------------ |
|
||||
| ------------ | ------------ | ------------ | ----------- | ------------ |
|
||||
| Y | Anchor point Y for: | undefined | undefined | undefined |
|
||||
| X | Anchor point X for: | undefined | undefined | undefined |
|
||||
| Y | Anchor point Y for: | (unused) | (unused) | (unused) |
|
||||
| Y | Anchor point Y for: | Type-0 | Type-1 | Type-2 |
|
||||
| X | Anchor point X for: | Type-0 | Type-1 | Type-2 |
|
||||
| **MSB** | | | | |
|
||||
|
||||
<MSB,Red> 1Y1Y1Y1Y 1Y2Y2Y2Y 1Y3Y3Y3Y <LSB,Blue>
|
||||
<MSB,Red> 1X1X1X1X 1X2X2X2X 1X3X3X3X <LSB,Blue>
|
||||
<MSB,Red> 1Y1Y1Y1Y 2Y2Y2Y2Y 3Y3Y3Y3Y <LSB,Blue>
|
||||
<MSB,Red> 1X1X1X1X 2X2X2X2X 3X3X3X3X <LSB,Blue>
|
||||
|
||||
where Red is first, Green is second, Blue is the third diacritics.
|
||||
MSB for each word must be set so that the pixel would appear brighter on the image editor.
|
||||
(the font program will only read low 7 bits for each RGB channel)
|
||||
|
||||
Each X and Y numbers are SIGN AND MAGNITUDE 8-Bit Integer.
|
||||
|
||||
X-positive: nudges towards left
|
||||
Y-positive: nudges towards down
|
||||
|
||||
#### Diacritics Type Bit Encoding
|
||||
|
||||
|
||||
Binary file not shown.
@@ -370,10 +370,9 @@ def build_font(assets_dir, output_path, no_bitmap=False, no_features=False):
|
||||
x_offset = 0
|
||||
x_offset -= g.props.nudge_x * SCALE
|
||||
|
||||
# For STACK_DOWN marks (below-base diacritics), negative nudge_y
|
||||
# means "shift content down to below baseline". The sign convention
|
||||
# is opposite to non-marks where positive nudge_y means shift down.
|
||||
if g.props.stack_where == SC.STACK_DOWN and g.props.write_on_top >= 0:
|
||||
# For marks (write_on_top >= 0), positive nudge_y means shift UP
|
||||
# in the bitmap engine (opposite to non-marks where positive = down).
|
||||
if g.props.write_on_top >= 0:
|
||||
y_offset = g.props.nudge_y * SCALE
|
||||
else:
|
||||
y_offset = -g.props.nudge_y * SCALE
|
||||
|
||||
@@ -38,6 +38,7 @@ class GlyphProps:
|
||||
has_kern_data: bool = False
|
||||
is_kern_y_type: bool = False
|
||||
kerning_mask: int = 255
|
||||
dot_removal: Optional[int] = None # codepoint to replace with when followed by a STACK_UP mark
|
||||
directive_opcode: int = 0
|
||||
directive_arg1: int = 0
|
||||
directive_arg2: int = 0
|
||||
@@ -131,7 +132,8 @@ def parse_variable_sheet(image, sheet_index, cell_w, cell_h, cols, is_xy_swapped
|
||||
|
||||
# Kerning data
|
||||
kerning_bit1 = _tagify(image.get_pixel(code_start_x, code_start_y + 6))
|
||||
# kerning_bit2 and kerning_bit3 are reserved
|
||||
kerning_bit2 = _tagify(image.get_pixel(code_start_x, code_start_y + 7))
|
||||
dot_removal = None if kerning_bit2 == 0 else (kerning_bit2 >> 8)
|
||||
is_kern_y_type = (kerning_bit1 & 0x80000000) != 0
|
||||
kerning_mask = (kerning_bit1 >> 8) & 0xFFFFFF
|
||||
has_kern_data = (kerning_bit1 & 0xFF) != 0
|
||||
@@ -188,7 +190,7 @@ def parse_variable_sheet(image, sheet_index, cell_w, cell_h, cols, is_xy_swapped
|
||||
align_where=align_where, write_on_top=write_on_top,
|
||||
stack_where=stack_where, ext_info=ext_info,
|
||||
has_kern_data=has_kern_data, is_kern_y_type=is_kern_y_type,
|
||||
kerning_mask=kerning_mask,
|
||||
kerning_mask=kerning_mask, dot_removal=dot_removal,
|
||||
directive_opcode=directive_opcode, directive_arg1=directive_arg1,
|
||||
directive_arg2=directive_arg2,
|
||||
)
|
||||
|
||||
@@ -70,6 +70,11 @@ languagesystem sund dflt;
|
||||
if ccmp_code:
|
||||
parts.append(ccmp_code)
|
||||
|
||||
# ccmp: dot removal (e.g. i→ı, j→ȷ when followed by STACK_UP marks)
|
||||
dot_removal_code = _generate_dot_removal(glyphs, has)
|
||||
if dot_removal_code:
|
||||
parts.append(dot_removal_code)
|
||||
|
||||
# Hangul jamo GSUB assembly
|
||||
hangul_code = _generate_hangul_gsub(glyphs, has, jamo_data)
|
||||
if hangul_code:
|
||||
@@ -162,6 +167,54 @@ def _generate_ccmp(replacewith_subs, has):
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def _generate_dot_removal(glyphs, has):
|
||||
"""Generate ccmp contextual substitution for dot removal.
|
||||
|
||||
When a base glyph tagged with dot_removal (kerning bit 2, pixel Y+7) is
|
||||
followed by a STACK_UP mark, substitute the base with its dotless form.
|
||||
Matches the Kotlin engine's dotRemoval logic.
|
||||
"""
|
||||
# Collect all STACK_UP marks
|
||||
stack_up_marks = []
|
||||
for cp, g in glyphs.items():
|
||||
if g.props.write_on_top >= 0 and g.props.stack_where == SC.STACK_UP and has(cp):
|
||||
stack_up_marks.append(cp)
|
||||
|
||||
if not stack_up_marks:
|
||||
return ""
|
||||
|
||||
# Collect all base glyphs with dot_removal
|
||||
dot_removal_subs = []
|
||||
for cp, g in glyphs.items():
|
||||
if g.props.dot_removal is not None and has(cp) and has(g.props.dot_removal):
|
||||
dot_removal_subs.append((cp, g.props.dot_removal))
|
||||
|
||||
if not dot_removal_subs:
|
||||
return ""
|
||||
|
||||
lines = []
|
||||
|
||||
# Define the STACK_UP marks class
|
||||
mark_names = ' '.join(glyph_name(cp) for cp in sorted(stack_up_marks))
|
||||
lines.append(f"@stackUpMarks = [{mark_names}];")
|
||||
lines.append("")
|
||||
|
||||
# Single substitution lookup for the replacements
|
||||
lines.append("lookup DotRemoval {")
|
||||
for src_cp, dst_cp in sorted(dot_removal_subs):
|
||||
lines.append(f" sub {glyph_name(src_cp)} by {glyph_name(dst_cp)};")
|
||||
lines.append("} DotRemoval;")
|
||||
lines.append("")
|
||||
|
||||
# Contextual rules in ccmp
|
||||
lines.append("feature ccmp {")
|
||||
for src_cp, _ in sorted(dot_removal_subs):
|
||||
lines.append(f" sub {glyph_name(src_cp)}' lookup DotRemoval @stackUpMarks;")
|
||||
lines.append("} ccmp;")
|
||||
|
||||
return '\n'.join(lines)
|
||||
|
||||
|
||||
def _generate_hangul_gsub(glyphs, has, jamo_data):
|
||||
"""
|
||||
Generate Hangul jamo GSUB lookups for syllable assembly.
|
||||
@@ -1750,7 +1803,7 @@ def _generate_mark(glyphs, has):
|
||||
|
||||
mark_groups = {} # (mark_type, align, is_dia, stack_cat) -> [(cp, g), ...]
|
||||
for cp, g in marks.items():
|
||||
is_dia = (0x0300 <= cp <= 0x036F)
|
||||
is_dia = True # all marks (write_on_top >= 0) are diacritics; Kotlin applies lowheight shiftdown unconditionally
|
||||
sc = _stack_cat(g.props.stack_where)
|
||||
key = (g.props.write_on_top, g.props.align_where, is_dia, sc)
|
||||
mark_groups.setdefault(key, []).append((cp, g))
|
||||
@@ -1846,7 +1899,9 @@ def _generate_mark(glyphs, has):
|
||||
# Lowheight adjustment for combining diacritical marks:
|
||||
# shift base anchor Y down so diacritics sit closer to
|
||||
# the shorter base glyph.
|
||||
if is_dia and g.props.is_low_height:
|
||||
# Only applies to 'up' marks (and overlay), not 'dn',
|
||||
# matching Kotlin which only adjusts in STACK_UP/STACK_UP_N_DOWN.
|
||||
if is_dia and g.props.is_low_height and scat != 'dn':
|
||||
if mark_type == 2: # overlay
|
||||
ay -= SC.H_OVERLAY_LOWERCASE_SHIFTDOWN * SC.SCALE
|
||||
else: # above (type 0)
|
||||
@@ -1878,12 +1933,13 @@ def _generate_mark(glyphs, has):
|
||||
lines.append(f"lookup {mkmk_name} {{")
|
||||
|
||||
if scat == 'up':
|
||||
m2y = SC.ASCENT + SC.H_DIACRITICS * SC.SCALE
|
||||
m2y_base = SC.ASCENT + SC.H_DIACRITICS * SC.SCALE
|
||||
else: # 'dn'
|
||||
m2y = SC.ASCENT - SC.H_DIACRITICS * SC.SCALE
|
||||
m2y_base = SC.ASCENT - SC.H_DIACRITICS * SC.SCALE
|
||||
|
||||
for cp, g in mark_list:
|
||||
mx = mark_anchors.get(cp, 0)
|
||||
m2y = m2y_base
|
||||
lines.append(
|
||||
f" pos mark {glyph_name(cp)}"
|
||||
f" <anchor {mx} {m2y}> mark {class_name};"
|
||||
@@ -1893,6 +1949,46 @@ def _generate_mark(glyphs, has):
|
||||
lines.append("")
|
||||
mkmk_lookup_names.append(mkmk_name)
|
||||
|
||||
# --- Nudge-Y gap correction for MarkToMark ---
|
||||
# Without cascade, the gap between consecutive 'up' marks is
|
||||
# H_DIACRITICS + nudge_y_2 - nudge_y_1
|
||||
# which is less than H_DIACRITICS when nudge_y_1 > nudge_y_2
|
||||
# (e.g. Cyrillic uni2DED nudge=2 followed by uni0487 nudge=0).
|
||||
# Add contextual positioning to compensate: shift mark2 up by
|
||||
# (nudge_y_1 - nudge_y_2) * SCALE for each such pair.
|
||||
# This keeps Thai correct (same nudge on both marks → no correction)
|
||||
# while fixing Cyrillic (different nudge → correction applied).
|
||||
nudge_groups = {} # nudge_y -> [glyph_name, ...]
|
||||
for (mark_type, align, is_dia, scat), mark_list in sorted(mark_groups.items()):
|
||||
if scat != 'up':
|
||||
continue
|
||||
for cp, g in mark_list:
|
||||
ny = g.props.nudge_y
|
||||
nudge_groups.setdefault(ny, []).append(glyph_name(cp))
|
||||
|
||||
distinct_nudges = sorted(nudge_groups.keys())
|
||||
correction_pairs = []
|
||||
for n1 in distinct_nudges:
|
||||
for n2 in distinct_nudges:
|
||||
if n1 > n2:
|
||||
correction_pairs.append((n1, n2, (n1 - n2) * SC.SCALE))
|
||||
|
||||
if correction_pairs:
|
||||
for ny, glyphs in sorted(nudge_groups.items()):
|
||||
lines.append(f"@up_nudge_{ny} = [{' '.join(sorted(glyphs))}];")
|
||||
lines.append("")
|
||||
|
||||
mkmk_corr_name = "mkmk_nudge_correct"
|
||||
lines.append(f"lookup {mkmk_corr_name} {{")
|
||||
for n1, n2, val in correction_pairs:
|
||||
lines.append(
|
||||
f" pos @up_nudge_{n1} <0 0 0 0>"
|
||||
f" @up_nudge_{n2} <0 {val} 0 0>;"
|
||||
)
|
||||
lines.append(f"}} {mkmk_corr_name};")
|
||||
lines.append("")
|
||||
mkmk_lookup_names.append(mkmk_corr_name)
|
||||
|
||||
# Register MarkToBase lookups under mark.
|
||||
# dev2 is excluded: HarfBuzz/DirectWrite use abvm for Devanagari marks.
|
||||
# deva is INCLUDED: CoreText's old-Indic shaper may need mark/mkmk
|
||||
|
||||
@@ -72,6 +72,9 @@ SHEET_ALPHABETIC_PRESENTATION_FORMS = 38
|
||||
SHEET_HENTAIGANA_VARW = 39
|
||||
SHEET_CONTROL_PICTURES_VARW = 40
|
||||
SHEET_LEGACY_COMPUTING_VARW = 41
|
||||
SHEET_CYRILIC_EXTB_VARW = 42
|
||||
SHEET_CYRILIC_EXTA_VARW = 43
|
||||
SHEET_CYRILIC_EXTC_VARW = 44
|
||||
|
||||
SHEET_UNKNOWN = 254
|
||||
|
||||
@@ -118,6 +121,9 @@ FILE_LIST = [
|
||||
"hentaigana_variable.tga",
|
||||
"control_pictures_variable.tga",
|
||||
"symbols_for_legacy_computing_variable.tga",
|
||||
"cyrilic_extB_variable.tga",
|
||||
"cyrilic_extA_variable.tga",
|
||||
"cyrilic_extC_variable.tga",
|
||||
]
|
||||
|
||||
CODE_RANGE = [
|
||||
@@ -151,7 +157,7 @@ CODE_RANGE = [
|
||||
list(range(0xA720, 0xA800)), # 27: Latin Ext D
|
||||
list(range(0x20A0, 0x20D0)), # 28: Currencies
|
||||
list(range(0xFFE00, 0xFFFA0)), # 29: Internal
|
||||
list(range(0x2100, 0x2150)), # 30: Letterlike
|
||||
list(range(0x2100, 0x2200)), # 30: Letterlike
|
||||
list(range(0x1F100, 0x1F200)), # 31: Enclosed Alphanum Supl
|
||||
list(range(0x0B80, 0x0C00)) + list(range(0xF00C0, 0xF0100)), # 32: Tamil
|
||||
list(range(0x980, 0xA00)), # 33: Bengali
|
||||
@@ -163,6 +169,9 @@ CODE_RANGE = [
|
||||
list(range(0x1B000, 0x1B170)), # 39: Hentaigana
|
||||
list(range(0x2400, 0x2440)), # 40: Control Pictures
|
||||
list(range(0x1FB00, 0x1FC00)), # 41: Legacy Computing
|
||||
list(range(0xA640, 0xA6A0)), # 42: Cyrillic Ext B
|
||||
list(range(0x2DE0, 0x2E00)), # 43: Cyrillic Ext A
|
||||
list(range(0x1C80, 0x1C8F)), # 43: Cyrillic Ext C
|
||||
]
|
||||
|
||||
CODE_RANGE_HANGUL_COMPAT = range(0x3130, 0x3190)
|
||||
@@ -539,5 +548,8 @@ def index_y(sheet_index, c):
|
||||
SHEET_HENTAIGANA_VARW: lambda: (c - 0x1B000) // 16,
|
||||
SHEET_CONTROL_PICTURES_VARW: lambda: (c - 0x2400) // 16,
|
||||
SHEET_LEGACY_COMPUTING_VARW: lambda: (c - 0x1FB00) // 16,
|
||||
SHEET_CYRILIC_EXTB_VARW: lambda: (c - 0xA640) // 16,
|
||||
SHEET_CYRILIC_EXTA_VARW: lambda: (c - 0x2DE0) // 16,
|
||||
SHEET_CYRILIC_EXTC_VARW: lambda: (c - 0x1C80) // 16,
|
||||
SHEET_HANGUL: lambda: 0,
|
||||
}.get(sheet_index, lambda: c // 16)()
|
||||
|
||||
Binary file not shown.
BIN
demo.PNG
BIN
demo.PNG
Binary file not shown.
|
Before Width: | Height: | Size: 168 KiB After Width: | Height: | Size: 177 KiB |
@@ -25,6 +25,7 @@ How multilingual? Real multilingual!
|
||||
আমি কাঁচ খেতে পারি, তাতে আমার কোনো ক্ষতি হয় না।
|
||||
Под южно дърво, цъфтящо в синьо, бягаше малко пухкаво зайче
|
||||
ᎠᏍᎦᏯᎡᎦᎢᎾᎨᎢᎣᏍᏓᎤᎩᏍᏗᎥᎴᏓᎯᎲᎢᏔᎵᏕᎦᏟᏗᏖᎸᎳᏗᏗᎧᎵᎢᏘᎴᎩ ᏙᏱᏗᏜᏫᏗᏣᏚᎦᏫᏛᏄᏓᎦᏝᏃᎠᎾᏗᎭᏞᎦᎯᎦᏘᏓᏠᎨᏏᏕᏡᎬᏢᏓᏥᏩᏝᎡᎢᎪᎢ ᎠᎦᏂᏗᎮᎢᎫᎩᎬᏩᎴᎢᎠᏆᏅᏛᎫᏊᎾᎥᎠᏁᏙᎲᏐᏈᎵᎤᎩᎸᏓᏭᎷᏤᎢᏏᏉᏯᏌᏊ ᎤᏂᏋᎢᏡᎬᎢᎰᏩᎬᏤᎵᏍᏗᏱᎩᎱᎱᎤᎩᎴᎢᏦᎢᎠᏂᏧᏣᏨᎦᏥᎪᎥᏌᏊᎤᎶᏒᎢᎢᏡᎬᎢ ᎹᎦᎺᎵᏥᎻᎼᏏᎽᏗᏩᏂᎦᏘᎾᎿᎠᏁᎬᎢᏅᎩᎾᏂᎡᎢᏌᎶᎵᏎᎷᎠᏑᏍᏗᏪᎩ ᎠᎴ ᏬᏗᏲᏭᎾᏓᏍᏓᏴᏁᎢᎤᎦᏅᏮᏰᎵᏳᏂᎨᎢ
|
||||
Ѳеѡфа́нъ и҆ Алеѯі́й, ѕѣлѡ̀ возлюби́вше ѱалти́рь, воспѣ́ша при свѣ́тѣ ѕвѣ́здъ, помазꙋ́юще сщ҃е́нное мѵ́ро; серафими мн̑оꙮ҆читїи̑, ꙗ҆́кѡ ѻ҆́гнь, ѡ҆крꙋжа́хꙋ прⷭ҇то́лъ Бж҃їй, и҆ всѧ̀ землѧ̀ и҆спо́лнисѧ свѣ́та, ꙗ҆́кѡ ѕмі́й попра́нъ є҆́сть
|
||||
Příliš žluťoučký kůň úpěl ďábelské ódy
|
||||
Quizdeltagerne spiste jordbær med fløde, mens cirkusklovnen Walther spillede på xylofon
|
||||
PACK MY BOX WITH FIVE DOZEN LIQUOR JUGS
|
||||
@@ -104,6 +105,10 @@ How multilingual? Real multilingual!
|
||||
|
||||
‣ Full support for Archaic Kana/Hentaigana
|
||||
|
||||
серафими мн̑оꙮ҆читїи̑, ꙗ҆́кѡ ѻ҆́гнь, ѡ҆крꙋжа́хꙋ прⷭ҇то́лъ Бж҃їй, и҆ всѧ̀ землѧ̀ и҆спо́лнисѧ свѣ́та
|
||||
|
||||
‣ Fan of Church Slavonic? We’ve got you!
|
||||
|
||||
Supported Unicode Blocks:
|
||||
|
||||
⁃ Basic Latin
|
||||
@@ -111,6 +116,7 @@ How multilingual? Real multilingual!
|
||||
⁃ Latin Extended Additional
|
||||
⁃ Latin Extended-A/B/C/D
|
||||
⁃ Armenian
|
||||
⁃ Arrows
|
||||
⁃ Bengaliᶠⁱ
|
||||
⁃ Braille Patterns
|
||||
⁃ Cherokee⁷
|
||||
@@ -120,8 +126,9 @@ How multilingual? Real multilingual!
|
||||
⁃ Combining Diacritical Marks
|
||||
⁃ Control Pictures
|
||||
⁃ Currency Symbols
|
||||
⁃ Cyrillicᴭ
|
||||
⁃ Cyrillic Supplementᴭ
|
||||
⁃ Cyrillic
|
||||
⁃ Cyrillic Supplement
|
||||
⁃ Cyrillic Extended-A/B/C
|
||||
⁃ Devanagari
|
||||
⁃ Enclosed Alphanumeric Supplement
|
||||
⁃ General Punctuations
|
||||
@@ -140,6 +147,7 @@ How multilingual? Real multilingual!
|
||||
⁃ Katakana Phonetic Extensions
|
||||
⁃ Kana Supplement
|
||||
⁃ Kana Extended-A
|
||||
⁃ Number Forms
|
||||
⁃ Small Kana Extension
|
||||
⁃ Letterlike Symbols
|
||||
⁃ Phonetic Extensions
|
||||
@@ -153,7 +161,7 @@ How multilingual? Real multilingual!
|
||||
⁃ Tamil
|
||||
⁃ Thai
|
||||
|
||||
ᴭ No support for archæic letters ᴱ No support for Coptic
|
||||
ᴱ No support for Coptic
|
||||
ᶠⁱ No support for ligatures ჼ Mkhedruli only
|
||||
⁶ ⁷ ⁹ ¹²·¹ Up to the specified Unicode version
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
--- Pixel 0
|
||||
- Lowheight bit
|
||||
- encoding: has pixel - it's low height
|
||||
- used by the diacritics system to quickly look up if the character is low height without parsing the Pixel 1
|
||||
- bit must be set if above-diacritics should be lowered (e.g. lowercase b, which has 'A' shape bit but considered lowheight)
|
||||
|
||||
### Legends
|
||||
#
|
||||
@@ -106,3 +106,5 @@ dot removal for diacritics:
|
||||
- encoding:
|
||||
- <MSB> RRRRRRRR GGGGGGGG BBBBBBBB <LSB>
|
||||
|
||||
--- Pixel 3
|
||||
Unused for now.
|
||||
BIN
src/assets/ascii_variable.tga
LFS
BIN
src/assets/ascii_variable.tga
LFS
Binary file not shown.
Binary file not shown.
BIN
src/assets/cyrilic_extA_variable.tga
LFS
Normal file
BIN
src/assets/cyrilic_extA_variable.tga
LFS
Normal file
Binary file not shown.
BIN
src/assets/cyrilic_extB_variable.tga
LFS
Normal file
BIN
src/assets/cyrilic_extB_variable.tga
LFS
Normal file
Binary file not shown.
BIN
src/assets/cyrilic_extC_variable.tga
LFS
Normal file
BIN
src/assets/cyrilic_extC_variable.tga
LFS
Normal file
Binary file not shown.
Binary file not shown.
BIN
src/assets/cyrilic_variable.tga
LFS
BIN
src/assets/cyrilic_variable.tga
LFS
Binary file not shown.
BIN
src/assets/internal_variable.tga
LFS
BIN
src/assets/internal_variable.tga
LFS
Binary file not shown.
Binary file not shown.
BIN
src/assets/thai_variable.tga
LFS
BIN
src/assets/thai_variable.tga
LFS
Binary file not shown.
@@ -1,9 +1,13 @@
|
||||
package net.torvald.terrarumsansbitmap
|
||||
|
||||
import net.torvald.terrarumsansbitmap.gdx.CodePoint
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2021-11-25.
|
||||
*/
|
||||
data class DiacriticsAnchor(val type: Int, val x: Int, val y: Int, val xUsed: Boolean, val yUsed: Boolean)
|
||||
data class DiacriticsAnchor(val type: Int, val x: Int, val y: Int) {
|
||||
val isZero = (x == 0 && y == 0)
|
||||
}
|
||||
/**
|
||||
* Created by minjaesong on 2018-08-07.
|
||||
*/
|
||||
@@ -15,7 +19,7 @@ data class GlyphProps(
|
||||
val nudgeX: Int = 0,
|
||||
val nudgeY: Int = 0,
|
||||
|
||||
val diacriticsAnchors: Array<DiacriticsAnchor> = Array(6) { DiacriticsAnchor(it, 0, 0, false, false) },
|
||||
val diacriticsAnchors: Array<DiacriticsAnchor> = Array(6) { DiacriticsAnchor(it, 0, 0) },
|
||||
|
||||
val alignWhere: Int = 0, // ALIGN_LEFT..ALIGN_BEFORE
|
||||
|
||||
@@ -29,6 +33,8 @@ data class GlyphProps(
|
||||
val isKernYtype: Boolean = false,
|
||||
val kerningMask: Int = 255,
|
||||
|
||||
val dotRemoval: CodePoint? = null,
|
||||
|
||||
val directiveOpcode: Int = 0, // 8-bits wide
|
||||
val directiveArg1: Int = 0, // 8-bits wide
|
||||
val directiveArg2: Int = 0, // 8-bits wide
|
||||
@@ -95,10 +101,6 @@ data class GlyphProps(
|
||||
diacriticsAnchors.forEach {
|
||||
hash = hash xor it.type
|
||||
hash = hash * 16777619
|
||||
hash = hash xor (it.x or (if (it.xUsed) 128 else 0))
|
||||
hash = hash * 16777619
|
||||
hash = hash xor (it.y or (if (it.yUsed) 128 else 0))
|
||||
hash = hash * 16777619
|
||||
}
|
||||
|
||||
hash = hash xor tags
|
||||
|
||||
@@ -888,6 +888,9 @@ class TerrarumSansBitmap(
|
||||
SHEET_HENTAIGANA_VARW -> hentaiganaIndexY(ch)
|
||||
SHEET_CONTROL_PICTURES_VARW -> controlPicturesIndexY(ch)
|
||||
SHEET_LEGACY_COMPUTING_VARW -> legacyComputingIndexY(ch)
|
||||
SHEET_CYRILIC_EXTB_VARW -> cyrilicExtBIndexY(ch)
|
||||
SHEET_CYRILIC_EXTA_VARW -> cyrilicExtAIndexY(ch)
|
||||
SHEET_CYRILIC_EXTC_VARW -> cyrilicExtCIndexY(ch)
|
||||
else -> ch / 16
|
||||
}
|
||||
|
||||
@@ -918,9 +921,9 @@ class TerrarumSansBitmap(
|
||||
val isLowHeight = (pixmap.getPixel(codeStartX, codeStartY + 5).and(255) != 0)
|
||||
|
||||
// Keming machine parameters
|
||||
val kerningBit1 = pixmap.getPixel(codeStartX, codeStartY + 6).tagify()
|
||||
val kerningBit2 = pixmap.getPixel(codeStartX, codeStartY + 7).tagify()
|
||||
val kerningBit3 = pixmap.getPixel(codeStartX, codeStartY + 8).tagify()
|
||||
val kerningBit1 = pixmap.getPixel(codeStartX, codeStartY + 6).tagify() // glyph shape
|
||||
val kerningBit2 = pixmap.getPixel(codeStartX, codeStartY + 7).tagify() // dot removal
|
||||
val kerningBit3 = pixmap.getPixel(codeStartX, codeStartY + 8).tagify() // unused
|
||||
var isKernYtype = ((kerningBit1 and 0x80000000.toInt()) != 0)
|
||||
var kerningMask = kerningBit1.ushr(8).and(0xFFFFFF)
|
||||
val hasKernData = kerningBit1 and 255 != 0//(kerningBit1 and 255 != 0 && kerningMask != 0xFFFF)
|
||||
@@ -944,12 +947,12 @@ class TerrarumSansBitmap(
|
||||
val shift = (3 - (it % 3)) * 8
|
||||
val yPixel = pixmap.getPixel(codeStartX, codeStartY + yPos).tagify()
|
||||
val xPixel = pixmap.getPixel(codeStartX, codeStartY + yPos + 1).tagify()
|
||||
val yUsed = (yPixel ushr shift) and 128 != 0
|
||||
val xUsed = (xPixel ushr shift) and 128 != 0
|
||||
val y = if (yUsed) (yPixel ushr shift) and 127 else 0
|
||||
val x = if (xUsed) (xPixel ushr shift) and 127 else 0
|
||||
val ySgn = ((yPixel ushr shift) and 128).let { if (it == 0) -1 else 1 }
|
||||
val xSgn = ((xPixel ushr shift) and 128).let { if (it == 0) -1 else 1 }
|
||||
val y = ((yPixel ushr shift) and 127) * ySgn
|
||||
val x = ((xPixel ushr shift) and 127) * xSgn
|
||||
|
||||
DiacriticsAnchor(it, x, y, xUsed, yUsed)
|
||||
DiacriticsAnchor(it, x, y)
|
||||
}.toTypedArray()
|
||||
|
||||
val alignWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 15).and(255) != 0).toInt() shl y) }
|
||||
@@ -968,7 +971,9 @@ class TerrarumSansBitmap(
|
||||
GlyphProps.STACK_DONT
|
||||
else (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 18).and(255) != 0).toInt() shl y) }
|
||||
|
||||
glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, IntArray(15), hasKernData, isKernYtype, kerningMask, directiveOpcode, directiveArg1, directiveArg2)
|
||||
val dotRemoval = if (kerningBit2 == 0) null else kerningBit2.ushr(8)
|
||||
|
||||
glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, IntArray(15), hasKernData, isKernYtype, kerningMask, dotRemoval, directiveOpcode, directiveArg1, directiveArg2)
|
||||
|
||||
// extra info
|
||||
val extCount = glyphProps[code]?.requiredExtInfoCount() ?: 0
|
||||
@@ -1015,17 +1020,6 @@ class TerrarumSansBitmap(
|
||||
(0xD800..0xDFFF).forEach { glyphProps[it] = GlyphProps(0) }
|
||||
(0x100000..0x10FFFF).forEach { glyphProps[it] = GlyphProps(0) }
|
||||
(0xFFFA0..0xFFFFF).forEach { glyphProps[it] = GlyphProps(0) }
|
||||
|
||||
|
||||
// manually add width of one orphan insular letter
|
||||
// WARNING: glyphs in 0xA770..0xA778 has invalid data, further care is required
|
||||
glyphProps[0x1D79] = GlyphProps(9)
|
||||
|
||||
|
||||
// U+007F is DEL originally, but this font stores bitmap of Replacement Character (U+FFFD)
|
||||
// to this position. String replacer will replace U+FFFD into U+007F.
|
||||
glyphProps[0x7F] = GlyphProps(15)
|
||||
|
||||
}
|
||||
|
||||
private fun Int.halveWidth() = this / 2 + 1
|
||||
@@ -1120,6 +1114,7 @@ class TerrarumSansBitmap(
|
||||
var nonDiacriticCounter = 0 // index of last instance of non-diacritic char
|
||||
var stackUpwardCounter = 0 // TODO separate stack counter for centre- and right aligned
|
||||
var stackDownwardCounter = 0
|
||||
var nudgeUpHighWater = 0 // tracks max nudgeY seen in current stack, so subsequent marks with lower nudge still clear the previous one
|
||||
|
||||
val HALF_VAR_INIT = W_VAR_INIT.minus(1).div(2)
|
||||
|
||||
@@ -1198,6 +1193,7 @@ class TerrarumSansBitmap(
|
||||
|
||||
stackUpwardCounter = 0
|
||||
stackDownwardCounter = 0
|
||||
nudgeUpHighWater = 0
|
||||
}
|
||||
// FIXME HACK: using 0th diacritics' X-anchor pos as a type selector
|
||||
/*else if (thisProp.writeOnTop && thisProp.diacriticsAnchors[0].x == GlyphProps.DIA_JOINER) {
|
||||
@@ -1217,30 +1213,32 @@ class TerrarumSansBitmap(
|
||||
// set X pos according to alignment information
|
||||
posXbuffer[charIndex] = -thisProp.nudgeX +
|
||||
when (thisProp.alignWhere) {
|
||||
GlyphProps.ALIGN_LEFT, GlyphProps.ALIGN_BEFORE -> posXbuffer[nonDiacriticCounter]
|
||||
GlyphProps.ALIGN_LEFT, GlyphProps.ALIGN_BEFORE -> {
|
||||
val anchorPointX = if (itsProp.diacriticsAnchors[diacriticsType].isZero) itsProp.width else itsProp.diacriticsAnchors[diacriticsType].x
|
||||
|
||||
posXbuffer[nonDiacriticCounter] + anchorPointX
|
||||
}
|
||||
GlyphProps.ALIGN_RIGHT -> {
|
||||
// println("thisprop alignright $kerning, $extraWidth")
|
||||
|
||||
val anchorPoint =
|
||||
if (!itsProp.diacriticsAnchors[diacriticsType].xUsed) itsProp.width else itsProp.diacriticsAnchors[diacriticsType].x
|
||||
val anchorPointX = if (itsProp.diacriticsAnchors[diacriticsType].isZero) itsProp.width else itsProp.diacriticsAnchors[diacriticsType].x
|
||||
|
||||
extraWidth += thisProp.width
|
||||
posXbuffer[nonDiacriticCounter] + anchorPoint - W_VAR_INIT + kerning + extraWidth
|
||||
posXbuffer[nonDiacriticCounter] + anchorPointX - W_VAR_INIT + kerning + extraWidth
|
||||
}
|
||||
GlyphProps.ALIGN_CENTRE -> {
|
||||
val anchorPoint =
|
||||
if (!itsProp.diacriticsAnchors[diacriticsType].xUsed) itsProp.width.div(2) else itsProp.diacriticsAnchors[diacriticsType].x
|
||||
val anchorPointX = if (itsProp.diacriticsAnchors[diacriticsType].isZero) itsProp.width.div(2) else itsProp.diacriticsAnchors[diacriticsType].x
|
||||
|
||||
if (itsProp.alignWhere == GlyphProps.ALIGN_RIGHT) {
|
||||
if (thisChar in 0x900..0x902)
|
||||
posXbuffer[nonDiacriticCounter] + anchorPoint + (itsProp.width - 1).div(2)
|
||||
posXbuffer[nonDiacriticCounter] + anchorPointX + (itsProp.width - 1).div(2)
|
||||
else
|
||||
posXbuffer[nonDiacriticCounter] + anchorPoint + (itsProp.width + 1).div(2)
|
||||
posXbuffer[nonDiacriticCounter] + anchorPointX + (itsProp.width + 1).div(2)
|
||||
} else {
|
||||
if (thisChar in 0x900..0x902)
|
||||
posXbuffer[nonDiacriticCounter] + anchorPoint - (W_VAR_INIT + 1) / 2
|
||||
posXbuffer[nonDiacriticCounter] + anchorPointX - (W_VAR_INIT + 1) / 2
|
||||
else
|
||||
posXbuffer[nonDiacriticCounter] + anchorPoint - HALF_VAR_INIT
|
||||
posXbuffer[nonDiacriticCounter] + anchorPointX - HALF_VAR_INIT
|
||||
}
|
||||
}
|
||||
else -> throw InternalError("Unsupported alignment: ${thisProp.alignWhere}")
|
||||
@@ -1277,14 +1275,14 @@ class TerrarumSansBitmap(
|
||||
// set Y pos according to diacritics position
|
||||
when (thisProp.stackWhere) {
|
||||
GlyphProps.STACK_DOWN -> {
|
||||
posYbuffer[charIndex] = (-thisProp.nudgeY + H_DIACRITICS * stackDownwardCounter) * flipY.toSign()
|
||||
posYbuffer[charIndex] = (-thisProp.nudgeY + H_DIACRITICS * stackDownwardCounter) * flipY.toSign() - thisProp.nudgeY
|
||||
stackDownwardCounter++
|
||||
}
|
||||
GlyphProps.STACK_UP -> {
|
||||
posYbuffer[charIndex] = -thisProp.nudgeY + (-H_DIACRITICS * stackUpwardCounter + -thisProp.nudgeY) * flipY.toSign()
|
||||
val effectiveNudge = maxOf(thisProp.nudgeY, nudgeUpHighWater)
|
||||
posYbuffer[charIndex] = -effectiveNudge + (-H_DIACRITICS * stackUpwardCounter + -effectiveNudge) * flipY.toSign() + effectiveNudge
|
||||
// shift down on lowercase if applicable
|
||||
if (getSheetType(thisChar) in autoShiftDownOnLowercase &&
|
||||
lastNonDiacriticChar.isLowHeight()) {
|
||||
if (lastNonDiacriticChar.isLowHeight()) {
|
||||
//dbgprn("AAARRRRHHHH for character ${thisChar.toHex()}")
|
||||
//dbgprn("lastNonDiacriticChar: ${lastNonDiacriticChar.toHex()}")
|
||||
//dbgprn("cond: ${thisProp.alignXPos == GlyphProps.DIA_OVERLAY}, charIndex: $charIndex")
|
||||
@@ -1294,6 +1292,7 @@ class TerrarumSansBitmap(
|
||||
posYbuffer[charIndex] += H_STACKUP_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
|
||||
}
|
||||
|
||||
nudgeUpHighWater = effectiveNudge
|
||||
stackUpwardCounter++
|
||||
|
||||
// dbgprn("lastNonDiacriticChar: ${lastNonDiacriticChar.charInfo()}; stack counter: $stackUpwardCounter")
|
||||
@@ -1302,22 +1301,25 @@ class TerrarumSansBitmap(
|
||||
posYbuffer[charIndex] = (-thisProp.nudgeY + H_DIACRITICS * stackDownwardCounter) * flipY.toSign()
|
||||
stackDownwardCounter++
|
||||
|
||||
|
||||
posYbuffer[charIndex] = (-thisProp.nudgeY + -H_DIACRITICS * stackUpwardCounter) * flipY.toSign()
|
||||
val effectiveNudge = maxOf(thisProp.nudgeY, nudgeUpHighWater)
|
||||
posYbuffer[charIndex] = (-effectiveNudge + -H_DIACRITICS * stackUpwardCounter) * flipY.toSign()
|
||||
// shift down on lowercase if applicable
|
||||
if (getSheetType(thisChar) in autoShiftDownOnLowercase &&
|
||||
lastNonDiacriticChar.isLowHeight()) {
|
||||
if (lastNonDiacriticChar.isLowHeight()) {
|
||||
if (diacriticsType == GlyphProps.DIA_OVERLAY)
|
||||
posYbuffer[charIndex] += H_OVERLAY_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
|
||||
else
|
||||
posYbuffer[charIndex] += H_STACKUP_LOWERCASE_SHIFTDOWN * flipY.toSign() // if minus-assign doesn't work, try plus-assign
|
||||
}
|
||||
|
||||
nudgeUpHighWater = effectiveNudge
|
||||
stackUpwardCounter++
|
||||
}
|
||||
// for BEFORE_N_AFTER, do nothing in here
|
||||
}
|
||||
|
||||
// nudge Y pos according to anchor position
|
||||
posYbuffer[charIndex] -= itsProp.diacriticsAnchors[diacriticsType].y
|
||||
|
||||
// Don't reset extraWidth here!
|
||||
}
|
||||
}
|
||||
@@ -1327,7 +1329,7 @@ class TerrarumSansBitmap(
|
||||
if (str.isNotEmpty()) {
|
||||
val lastCharProp = glyphProps[str.last()]
|
||||
val penultCharProp = glyphProps[str[nonDiacriticCounter]] ?:
|
||||
(if (errorOnUnknownChar) throw throw InternalError("No GlyphProps for char '${str[nonDiacriticCounter]}' " +
|
||||
(if (errorOnUnknownChar) throw InternalError("No GlyphProps for char '${str[nonDiacriticCounter]}' " +
|
||||
"(${str[nonDiacriticCounter].charInfo()})") else nullProp)
|
||||
posXbuffer[posXbuffer.lastIndex] = posXbuffer[posXbuffer.lastIndex - 1] + // DON'T add 1 to house the shadow, it totally breaks stuffs
|
||||
if (lastCharProp != null && lastCharProp.writeOnTop >= 0) {
|
||||
@@ -1523,8 +1525,8 @@ class TerrarumSansBitmap(
|
||||
|
||||
}
|
||||
// for lowercase i and j, if cNext is a diacritic that goes on top, remove the dots
|
||||
else if (diacriticDotRemoval.containsKey(c) && (glyphProps[cNext]?.writeOnTop ?: -1) >= 0 && glyphProps[cNext]?.stackWhere == GlyphProps.STACK_UP) {
|
||||
seq.add(diacriticDotRemoval[c]!!)
|
||||
else if (glyphProps[c]!!.dotRemoval != null && (glyphProps[cNext]?.writeOnTop ?: -1) >= 0 && glyphProps[cNext]?.stackWhere == GlyphProps.STACK_UP) {
|
||||
seq.add(glyphProps[c]!!.dotRemoval!!)
|
||||
}
|
||||
|
||||
// BEGIN of tamil subsystem implementation
|
||||
@@ -2604,6 +2606,9 @@ class TerrarumSansBitmap(
|
||||
internal const val SHEET_HENTAIGANA_VARW = 39
|
||||
internal const val SHEET_CONTROL_PICTURES_VARW = 40
|
||||
internal const val SHEET_LEGACY_COMPUTING_VARW = 41
|
||||
internal const val SHEET_CYRILIC_EXTB_VARW = 42
|
||||
internal const val SHEET_CYRILIC_EXTA_VARW = 43
|
||||
internal const val SHEET_CYRILIC_EXTC_VARW = 44
|
||||
|
||||
internal const val SHEET_UNKNOWN = 254
|
||||
|
||||
@@ -2625,10 +2630,6 @@ class TerrarumSansBitmap(
|
||||
const val MOVABLE_BLOCK_1 = 0xFFFF0
|
||||
|
||||
|
||||
private val autoShiftDownOnLowercase = arrayOf(
|
||||
SHEET_DIACRITICAL_MARKS_VARW
|
||||
)
|
||||
|
||||
private val fileList = arrayOf( // MUST BE MATCHING WITH SHEET INDICES!!
|
||||
"ascii_variable.tga",
|
||||
"hangul_johab.tga",
|
||||
@@ -2672,6 +2673,9 @@ class TerrarumSansBitmap(
|
||||
"hentaigana_variable.tga",
|
||||
"control_pictures_variable.tga",
|
||||
"symbols_for_legacy_computing_variable.tga",
|
||||
"cyrilic_extB_variable.tga",
|
||||
"cyrilic_extA_variable.tga",
|
||||
"cyrilic_extC_variable.tga",
|
||||
)
|
||||
internal val codeRange = arrayOf( // MUST BE MATCHING WITH SHEET INDICES!!
|
||||
0..0xFF, // SHEET_ASCII_VARW
|
||||
@@ -2704,7 +2708,7 @@ class TerrarumSansBitmap(
|
||||
0xA720..0xA7FF, // SHEET_EXTD_VARW
|
||||
0x20A0..0x20CF, // SHEET_CURRENCIES_VARW
|
||||
0xFFE00..0xFFF9F, // SHEET_INTERNAL_VARW
|
||||
0x2100..0x214F, // SHEET_LETTERLIKE_MATHS_VARW
|
||||
0x2100..0x21FF, // SHEET_LETTERLIKE_MATHS_VARW
|
||||
0x1F100..0x1F1FF, // SHEET_ENCLOSED_ALPHNUM_SUPL_VARW
|
||||
(0x0B80..0x0BFF) + (0xF00C0..0xF00FF), // SHEET_TAMIL_VARW
|
||||
0x980..0x9FF, // SHEET_BENGALI_VARW
|
||||
@@ -2716,6 +2720,9 @@ class TerrarumSansBitmap(
|
||||
0x1B000..0x1B16F, // SHEET_HENTAIGANA_VARW
|
||||
0x2400..0x243F, // SHEET_CONTROL_PICTURES_VARW
|
||||
0x1FB00..0x1FBFF, // SHEET_LEGACY_COMPUTING_VARW
|
||||
0xA640..0xA69F, // SHEET_CYRILIC_EXTB_VARW
|
||||
0x2DE0..0x2DFF, // SHEET_CYRILIC_EXTA_VARW
|
||||
0x1C80..0x1C8F, // SHEET_CYRILIC_EXTC_VARW
|
||||
)
|
||||
private val codeRangeHangulCompat = 0x3130..0x318F
|
||||
|
||||
@@ -2733,11 +2740,6 @@ class TerrarumSansBitmap(
|
||||
0x20..0x7F,
|
||||
)
|
||||
|
||||
private val diacriticDotRemoval = hashMapOf(
|
||||
'i'.toInt() to 0x131,
|
||||
'j'.toInt() to 0x237
|
||||
)
|
||||
|
||||
internal fun Int.charInfo() = "U+${this.toString(16).padStart(4, '0').toUpperCase()}: ${Character.getName(this)}"
|
||||
|
||||
const val NQSP = 0x2000
|
||||
@@ -3066,6 +3068,9 @@ class TerrarumSansBitmap(
|
||||
private fun hentaiganaIndexY(c: CodePoint) = (c - 0x1B000) / 16
|
||||
private fun controlPicturesIndexY(c: CodePoint) = (c - 0x2400) / 16
|
||||
private fun legacyComputingIndexY(c: CodePoint) = (c - 0x1FB00) / 16
|
||||
private fun cyrilicExtBIndexY(c: CodePoint) = (c - 0xA640) / 16
|
||||
private fun cyrilicExtAIndexY(c: CodePoint) = (c - 0x2DE0) / 16
|
||||
private fun cyrilicExtCIndexY(c: CodePoint) = (c - 0x1C80) / 16
|
||||
|
||||
val charsetOverrideDefault = Character.toChars(CHARSET_OVERRIDE_DEFAULT).toSurrogatedString()
|
||||
val charsetOverrideBulgarian = Character.toChars(CHARSET_OVERRIDE_BG_BG).toSurrogatedString()
|
||||
|
||||
@@ -229,16 +229,16 @@ class TerrarumTypewriterBitmap(
|
||||
val nudgeY = nudgingBits.ushr(16).toByte().toInt() // signed 8-bit int
|
||||
|
||||
val diacriticsAnchors = (0..5).map {
|
||||
val yPos = 11 + (it / 3) * 2
|
||||
val yPos = 13 - (it / 3) * 2
|
||||
val shift = (3 - (it % 3)) * 8
|
||||
val yPixel = pixmap.getPixel(codeStartX, codeStartY + yPos).tagify()
|
||||
val xPixel = pixmap.getPixel(codeStartX, codeStartY + yPos + 1).tagify()
|
||||
val y = (yPixel ushr shift) and 127
|
||||
val x = (xPixel ushr shift) and 127
|
||||
val yUsed = (yPixel ushr shift) >= 128
|
||||
val xUsed = (yPixel ushr shift) >= 128
|
||||
val ySgn = ((yPixel ushr shift) and 128).let { if (it == 0) -1 else 1 }
|
||||
val xSgn = ((xPixel ushr shift) and 128).let { if (it == 0) -1 else 1 }
|
||||
val y = ((yPixel ushr shift) and 127) * ySgn
|
||||
val x = ((xPixel ushr shift) and 127) * xSgn
|
||||
|
||||
DiacriticsAnchor(it, x, y, xUsed, yUsed)
|
||||
DiacriticsAnchor(it, x, y)
|
||||
}.toTypedArray()
|
||||
|
||||
val alignWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 15).and(255) != 0).toInt() shl y) }
|
||||
|
||||
BIN
work_files/ascii_variable.psd
LFS
BIN
work_files/ascii_variable.psd
LFS
Binary file not shown.
Binary file not shown.
BIN
work_files/cyrilic_extA_variable.kra
LFS
Normal file
BIN
work_files/cyrilic_extA_variable.kra
LFS
Normal file
Binary file not shown.
BIN
work_files/cyrilic_extB_variable.kra
LFS
Normal file
BIN
work_files/cyrilic_extB_variable.kra
LFS
Normal file
Binary file not shown.
BIN
work_files/cyrilic_extC_variable.kra
LFS
Normal file
BIN
work_files/cyrilic_extC_variable.kra
LFS
Normal file
Binary file not shown.
Binary file not shown.
BIN
work_files/cyrilic_variable.psd
LFS
BIN
work_files/cyrilic_variable.psd
LFS
Binary file not shown.
BIN
work_files/insular_variable.psd
LFS
BIN
work_files/insular_variable.psd
LFS
Binary file not shown.
BIN
work_files/internal_variable.psd
LFS
BIN
work_files/internal_variable.psd
LFS
Binary file not shown.
BIN
work_files/kana.psd
LFS
BIN
work_files/kana.psd
LFS
Binary file not shown.
Binary file not shown.
BIN
work_files/thai_variable.psd
LFS
BIN
work_files/thai_variable.psd
LFS
Binary file not shown.
Reference in New Issue
Block a user