Skip to content

Commit aa7ac00

Browse files
committed
song: Support merging with combining characters to the left
1 parent 9b4c7fe commit aa7ac00

2 files changed

Lines changed: 22 additions & 3 deletions

File tree

blitzloop/layout.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,11 +119,14 @@ def add(self, molecule, get_atom_time, style, font, ruby_font):
119119
for atom in molecule.atoms:
120120
atom_x, atom_y = self.px, self.py
121121
edge_px = None
122+
edge_l_px = None
122123
glyphs = []
123124
# add the atom's base text as glyphs
124125
for i,c in enumerate(atom.text):
125126
if atom.particle_edge is not None and i == atom.particle_edge:
126127
edge_px = self.px
128+
if atom.particle_edge_l is not None and i == atom.particle_edge_l:
129+
edge_l_px = self.px
127130
self.text += c
128131
glyph = font.get_glyph(c)
129132
gi = GlyphInstance(glyph, self.px, self.py, style)
@@ -180,6 +183,8 @@ def add(self, molecule, get_atom_time, style, font, ruby_font):
180183
par_step += particle.steps
181184
ruby_glyphs += par_glyphs
182185
# center the ruby text over the atom
186+
if edge_l_px is not None:
187+
atom_x = edge_l_px
183188
if edge_px is not None:
184189
atom_width = edge_px - atom_x
185190
else:

blitzloop/song.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ def __init__(self, text):
4646
Particle.__init__(self, text)
4747
self.particles = None
4848
self.particle_edge = None
49+
self.particle_edge_l = None
4950

5051
@property
5152
def steps(self):
@@ -84,14 +85,15 @@ def __unicode__(self):
8485
return "Molecule<[%r]" % self.steps + " ".join(map(str, self.atoms)) + ">"
8586

8687
class JapaneseMolecule(Molecule):
87-
COMBINE_CHARS = "ぁぃぅぇぉゃゅょァィゥェォャュョ  ?!?!…。、.,-「」―-◇・”\""
88+
COMBINE_CHARS = "ぁぃぅぇぉゃゅょァィゥェォャュョ  ?!?!…。、.,-「」『』【】〈〉()[]《》―-◇・”\""
8889
SPACE = " "
8990

9091
def parse(self, source):
9192
self.atoms = []
9293
in_furi = False
9394
in_particle = False
9495
in_escape = False
96+
first_combinable = True
9597

9698
self.break_before = self.break_after = False
9799
self.row = None
@@ -123,8 +125,12 @@ def parse(self, source):
123125
in_particle = False
124126
if in_furi:
125127
self.atoms[-1].particles.append(Particle(particle_text))
128+
elif first_combinable and self.atoms:
129+
self.atoms[-1].particle_edge_l = len(self.atoms[-1].text)
130+
self.atoms[-1].text += particle_text
126131
else:
127132
self.atoms.append(Atom(particle_text))
133+
first_combinable = False
128134
continue
129135
elif c in "((":
130136
if in_furi:
@@ -139,20 +145,28 @@ def parse(self, source):
139145
elif c in "))" and in_furi:
140146
self.atoms[-1].particle_edge = len(self.atoms[-1].text)
141147
in_furi = False
148+
first_combinable = False
142149
continue
143-
else:
144-
in_escape = False
145150
if in_particle:
146151
particle_text += c
147152
elif c in self.COMBINE_CHARS and not in_escape and self.atoms:
148153
if in_furi:
149154
self.atoms[-1].particles[-1].text += c
150155
else:
151156
self.atoms[-1].text += c
157+
elif first_combinable and self.atoms:
158+
self.atoms[-1].particle_edge_l = len(self.atoms[-1].text)
159+
self.atoms[-1].text += c
160+
first_combinable = c in self.COMBINE_CHARS
152161
elif in_furi:
153162
self.atoms[-1].particles.append(Particle(c))
154163
else:
155164
self.atoms.append(Atom(c))
165+
if c not in self.COMBINE_CHARS or in_escape:
166+
first_combinable = False
167+
in_escape = False
168+
assert not (first_combinable and len(self.atoms) > 1)
169+
156170
if in_particle:
157171
raise ParseError("Incomplete particle")
158172
if in_furi:

0 commit comments

Comments
 (0)