def project_b(self, BLOCK): if BLOCK.implicit_ is None: P = BLOCK["class"] else: P = BLOCK["class"] + BLOCK.implicit_ H = hash(frozenset(P.items())) if BLOCK.stylehash is not None: H += 13 * BLOCK.stylehash try: return self.block_projections[H] except KeyError: # iterate through stack projection = _Layer(self._block_default) for B in chain((b for b in self.content if b["class"] <= P), (BLOCK,)): projection.overlay(B) projection["__runinfo__"] = generate_runinfo(projection["language"]) self.block_projections[H] = projection return projection
def project_b(self, BLOCK): if BLOCK.implicit_ is None: P = BLOCK['class'] else: P = BLOCK['class'] + BLOCK.implicit_ H = hash(frozenset(P.items())) if BLOCK.stylehash is not None: H += 13 * BLOCK.stylehash try: return self.block_projections[H] except KeyError: # iterate through stack projection = _Layer(self._block_default) for B in chain((b for b in self.content if b['class'] <= P), (BLOCK, )): projection.overlay(B) projection['__runinfo__'] = generate_runinfo( projection['language']) self.block_projections[H] = projection return projection
def bidir_levels(runinfo, text, BLOCK, F=None): if F is None: F = Tagcounter() else: F = F.copy() i = 0 j = i SS = [] CHAR_STYLES = [] o_fontinfo, t_fontinfo, e_fontinfo = _get_fontinfo(BLOCK, F, CHAR_STYLES) runinfo_stack = [runinfo] l = runinfo[0] RUNS = [(l, False, i, None, runinfo, o_fontinfo)] SP = _S_SPACES EMSP = _EMOJI_SPACES def sorting(k): if type(k) is str: if k in EMSP: if k in SP: return 0 else: return 2 else: return 1 else: return -1 emojijoin = False for K, G in groupby(text, key=sorting): if K >= 0: string = ''.join(G) j += len(string) if K == 1: if emojijoin and string == '\u200D': RUNS.append((l, True, i, j, runinfo, t_fontinfo)) emojijoin += 1 else: emojijoin = False if t_fontinfo[0]['capitals']: string = string.upper() if l % 2: choose_runinfo = runinfo, numeric_runinfo RUNS.extend([ l + flip, True, i + p, i + q, choose_runinfo[flip], t_fontinfo ] for flip, (p, q) in _raise_digits(string) if q - p) else: RUNS.append([l, True, i, j, runinfo, t_fontinfo]) elif K == 2: if emojijoin > 1: del RUNS[-(emojijoin - 1):] RUNS[-1][3] = j else: RUNS.append([l, 2, i, j, runinfo, e_fontinfo]) emojijoin = True else: emojijoin = False RUNS.extend((l, False, i + ii, sp, runinfo, o_fontinfo) for ii, sp in enumerate(string)) i = j SS.append(string) else: emojijoin = False for v in G: if type(v) is Reverse: if v['language'] is None: if len(runinfo_stack) > 1: old_runinfo = runinfo_stack.pop() runinfo = runinfo_stack[-1] if old_runinfo[0] != runinfo[0]: l -= 1 RUNS.append((l, False, i, v, runinfo, o_fontinfo)) else: RUNS.append((l, False, i, v, runinfo, o_fontinfo)) runinfo = generate_runinfo(v['language']) if runinfo[0] != runinfo_stack[-1][0]: l += 1 runinfo_stack.append(runinfo) SS.append('\u00A0') elif v is not None: if isinstance(v, Fontpost): F = o_fontinfo[1].copy() if v.countersign: F += v['class'] if v.stylehash is not None: CHAR_STYLES.append(v) o_fontinfo, t_fontinfo, e_fontinfo = _get_fontinfo( BLOCK, F, CHAR_STYLES) RUNS.append((l, False, i, v, runinfo, o_fontinfo)) else: F -= v['class'] if v['pop'] > 0: del CHAR_STYLES[-v['pop']:] RUNS.append((l, False, i, v, runinfo, o_fontinfo)) o_fontinfo, t_fontinfo, e_fontinfo = _get_fontinfo( BLOCK, F, CHAR_STYLES) SS.append('\u00AD') else: RUNS.append((l, False, i, v, runinfo, o_fontinfo)) SS.append('[') j += 1 i = j return ''.join(SS), RUNS
e_font = FSTYLE['__hb_emoji__'] e_factor = FSTYLE['__factor_emoji__'] emojifont = FSTYLE['__emoji__'] fontsize = FSTYLE['fontsize'] def get_emoji(glyph_index): return emojifont.generate_paint_function(glyph_index, fontsize, e_factor) # nontextual | text | emoji return (FSTYLE, F), (FSTYLE, t_font, t_factor, None), (FSTYLE, e_font, e_factor, get_emoji) numeric_runinfo = generate_runinfo('numeric') def bidir_levels(runinfo, text, BLOCK, F=None): if F is None: F = Tagcounter() else: F = F.copy() i = 0 j = i SS = [] CHAR_STYLES = [] o_fontinfo, t_fontinfo, e_fontinfo = _get_fontinfo(BLOCK, F, CHAR_STYLES) runinfo_stack = [runinfo] l = runinfo[0]
def bidir_levels(runinfo, text, BLOCK, F=None): if F is None: F = Tagcounter() else: F = F.copy() i = 0 j = i SS = [] CHAR_STYLES = [] o_fontinfo, t_fontinfo, e_fontinfo = _get_fontinfo(BLOCK, F, CHAR_STYLES) runinfo_stack = [runinfo] l = runinfo[0] RUNS = [(l, False, i, None, runinfo, o_fontinfo)] SP = _S_SPACES EMSP = _EMOJI_SPACES def sorting(k): if type(k) is str: if k in EMSP: if k in SP: return 0 else: return 2 else: return 1 else: return -1 emojijoin = False for K, G in groupby(text, key=sorting): if K >= 0: string = ''.join(G) j += len(string) if K == 1: if emojijoin and string == '\u200D': RUNS.append((l, True, i, j, runinfo, t_fontinfo)) emojijoin += 1 else: emojijoin = False if t_fontinfo[0]['capitals']: string = string.upper() if l % 2: choose_runinfo = runinfo, numeric_runinfo RUNS.extend([l + flip, True, i + p, i + q, choose_runinfo[flip], t_fontinfo] for flip, (p, q) in _raise_digits(string) if q - p) else: RUNS.append([l, True, i, j, runinfo, t_fontinfo]) elif K == 2: if emojijoin > 1: del RUNS[-(emojijoin - 1):] RUNS[-1][3] = j else: RUNS.append([l, 2, i, j, runinfo, e_fontinfo]) emojijoin = True else: emojijoin = False RUNS.extend((l, False, i + ii, sp, runinfo, o_fontinfo) for ii, sp in enumerate(string)) i = j SS.append(string) else: emojijoin = False for v in G: if type(v) is Reverse: if v['language'] is None: if len(runinfo_stack) > 1: old_runinfo = runinfo_stack.pop() runinfo = runinfo_stack[-1] if old_runinfo[0] != runinfo[0]: l -= 1 RUNS.append((l, False, i, v, runinfo, o_fontinfo)) else: RUNS.append((l, False, i, v, runinfo, o_fontinfo)) runinfo = generate_runinfo(v['language']) if runinfo[0] != runinfo_stack[-1][0]: l += 1 runinfo_stack.append(runinfo) SS.append('\u00A0') elif v is not None: if isinstance(v, Fontpost): F = o_fontinfo[1].copy() if v.countersign: F += v['class'] if v.stylehash is not None: CHAR_STYLES.append(v) o_fontinfo, t_fontinfo, e_fontinfo = _get_fontinfo(BLOCK, F, CHAR_STYLES) RUNS.append((l, False, i, v, runinfo, o_fontinfo)) else: F -= v['class'] if v['pop'] > 0: del CHAR_STYLES[-v['pop']:] RUNS.append((l, False, i, v, runinfo, o_fontinfo)) o_fontinfo, t_fontinfo, e_fontinfo = _get_fontinfo(BLOCK, F, CHAR_STYLES) SS.append('\u00AD') else: RUNS.append((l, False, i, v, runinfo, o_fontinfo)) SS.append('[') j += 1 i = j return ''.join(SS), RUNS
FSTYLE = BLOCK.KT.BSTYLES.project_t(BLOCK, F, CHAR_STYLES) t_font = FSTYLE['__hb_font__'] t_factor = FSTYLE['__factor__'] e_font = FSTYLE['__hb_emoji__'] e_factor = FSTYLE['__factor_emoji__'] emojifont = FSTYLE['__emoji__'] fontsize = FSTYLE['fontsize'] def get_emoji(glyph_index): return emojifont.generate_paint_function(glyph_index, fontsize, e_factor) # nontextual | text | emoji return (FSTYLE, F), (FSTYLE, t_font, t_factor, None), (FSTYLE, e_font, e_factor, get_emoji) numeric_runinfo = generate_runinfo('numeric') def bidir_levels(runinfo, text, BLOCK, F=None): if F is None: F = Tagcounter() else: F = F.copy() i = 0 j = i SS = [] CHAR_STYLES = [] o_fontinfo, t_fontinfo, e_fontinfo = _get_fontinfo(BLOCK, F, CHAR_STYLES) runinfo_stack = [runinfo] l = runinfo[0] RUNS = [(l, False, i, None, runinfo, o_fontinfo)]