#!/usr/bin/python3
# -*- coding: utf-8 -*-
# Time-stamp: <2008-06-23 22:21:26 ah>
"""
Provide an encoder for a font specification configuration: the encoder is fed
with Unicode characters one by one and determines the needed font switches
between the preceding and the current character.
"""
from __future__ import print_function
import sys
import re
import xml.dom.minidom
from dbtexmf.dblatex.xetex.fontspec import UnicodeInterval
from dbtexmf.dblatex.xetex.fsconfig import FontSpecConfig
class FontSpecEncoder:
"""
Encoder working with font specifications: it is fed
with Unicode characters one by one and it inserts the needed font switches
between the preceding and the current character.
"""
def __init__(self, configuration):
"""
Create a font specification encoder from the specified configuration
file (file name or file-like object).
"""
self._conf = FontSpecConfig(configuration)
self._cur_fontspec = None
self._ref_stack = [self._conf.default_fontspec]
def reset(self):
# Restart from the default fontspec to avoid a useless 'enter' from None
self._cur_fontspec = self._conf.default_fontspec
self._ref_stack = [self._conf.default_fontspec]
def _switch_to(self, fontspec):
"""
Insert the transition string, according to the newly selected
fontspec and the previously selected fontspec
"""
s = ""
# If the font hasn't changed, just insert optional inter-char material
if fontspec == self._cur_fontspec:
return fontspec.interchar()
# A new font is selected, so exit from current font stream
if self._cur_fontspec:
s += self._cur_fontspec.exit()
# Enter into the current font stream
self._cur_fontspec = fontspec
s += fontspec.enter()
return s
def _encode(self, char):
"""
Select the fontspec matching the specified <char>, and switch to
this font as current font.
The principle to find out the fontspec is:
- to find from the current font level a matching font
(the current font leaf or the direct font children)
- if no font is found try with the parent font, and so on,
up to the default root font (that must exist).
"""
fontspec = self._cur_fontspec or self._conf.default_fontspec
print("Current:", fontspec.id, file=sys.stderr)
fontspec = fontspec.match(char)
while not(fontspec):
leaf = self._ref_stack.pop()
fontspec = self._ref_stack[-1].match(char, excluded=leaf)
if fontspec != self._ref_stack[-1]:
self._ref_stack.append(fontspec)
return self._switch_to(fontspec)
def ignorechars(self, charset):
"Characters to ignore in font selection (maintain the current one)"
intervals = [ UnicodeInterval().from_char(c) for c in charset ]
self._conf.default_fontspec.add_ignored(intervals)
def encode(self, char):
"""
Return a string consisting of the specified character prepended by
all necessary font switching commands.
"""
return (self._encode(char), char)
def stop(self):
"""
Cleanly exit from the current fontspec
"""
if self._cur_fontspec:
s = self._cur_fontspec.exit()
self._cur_fontspec = None
return s