2021 advent calendar day 12,13

暫定多言語対応

前回絵文字判定はemojiにて判定
https://github.com/carpedm20/emoji/

今回は日本語の判定を追加
https://github.com/nakamura001/JIS_CharacterSet

日本語の第三、第四水準はNotoSansJPフォントにて、それ以外はUniFontにて代用。
近隣アジアのハングル、繁体字、簡体字はNotoフォントにて表示させたい感じではある(TM-m30Ⅱ-Hに並べる)
各文字コードの領域判定が必要だけど、全く知らないのが辛いところ。

Noto
https://fonts.google.com/noto

UniFont
https://unifoundry.com/unifont/

今回のソース↓↓↓

  • ダウンロード文字の登録もできるようにしました。
  • 外字領域管理をLRUで管理するようにしました。
  • 関数名を変更
import collections
from escpos.printer import Network
from PIL import Image, ImageDraw, ImageFont
import emoji

class Gaiji():

  USER_AREAS_ASCII = [
    b'\x20',b'\x21',b'\x22',b'\x23',b'\x24',b'\x25',b'\x26',b'\x27',b'\x28',b'\x29',b'\x2a',b'\x2b',b'\x2c',b'\x2d',b'\x2e',b'\x2f',
    b'\x30',b'\x31',b'\x32',b'\x33',b'\x34',b'\x35',b'\x36',b'\x37',b'\x38',b'\x39',b'\x3a',b'\x3b',b'\x3c',b'\x3d',b'\x3e',b'\x3f',
    b'\x40',b'\x41',b'\x42',b'\x43',b'\x44',b'\x45',b'\x46',b'\x47',b'\x48',b'\x49',b'\x4a',b'\x4b',b'\x4c',b'\x4d',b'\x4e',b'\x4f',
    b'\x50',b'\x51',b'\x52',b'\x53',b'\x54',b'\x55',b'\x56',b'\x57',b'\x58',b'\x59',b'\x5a',b'\x5b',b'\x5c',b'\x5d',b'\x5e',b'\x5f',
    b'\x60',b'\x61',b'\x62',b'\x63',b'\x64',b'\x65',b'\x66',b'\x67',b'\x68',b'\x69',b'\x6a',b'\x6b',b'\x6c',b'\x6d',b'\x6e',b'\x6f',
    b'\x70',b'\x71',b'\x72',b'\x73',b'\x74',b'\x75',b'\x76',b'\x77',b'\x78',b'\x79',b'\x7a',b'\x7b',b'\x7c',b'\x7d',b'\x7e',
  ]

  USER_KANJI_AREAS_SJIS = [
    b'\x40',b'\x41',b'\x42',b'\x43',b'\x44',b'\x45',b'\x46',b'\x47',b'\x48',b'\x49',b'\x4a',b'\x4b',b'\x4c',b'\x4d',b'\x4e',b'\x4f',
    b'\x50',b'\x51',b'\x52',b'\x53',b'\x54',b'\x55',b'\x56',b'\x57',b'\x58',b'\x59',b'\x5a',b'\x5b',b'\x5c',b'\x5d',b'\x5e',b'\x5f',
    b'\x60',b'\x61',b'\x62',b'\x63',b'\x64',b'\x65',b'\x66',b'\x67',b'\x68',b'\x69',b'\x6a',b'\x6b',b'\x6c',b'\x6d',b'\x6e',b'\x6f',
    b'\x70',b'\x71',b'\x72',b'\x73',b'\x74',b'\x75',b'\x76',b'\x77',b'\x78',b'\x79',b'\x7a',b'\x7b',b'\x7c',b'\x7d',b'\x7e',
    b'\x80',b'\x81',b'\x82',b'\x83',b'\x84',b'\x85',b'\x86',b'\x87',b'\x88',b'\x89',b'\x8a',b'\x8b',b'\x8c',b'\x8d',b'\x8e',b'\x8f',
    b'\x90',b'\x91',b'\x92',b'\x93',b'\x94',b'\x95',b'\x96',b'\x97',b'\x98',b'\x99',b'\x9a',b'\x9b',b'\x9c',b'\x9d',b'\x9e',
  ]

  def __init__(self, Network):
    """初期化

    :param Network:   ネットワークプリンタークラス
    """
    self.user_areas  = collections.OrderedDict()
    self.gaiji_areas = collections.OrderedDict()

    for area in self.USER_AREAS_ASCII:
      self.user_areas[area] = ''

    for area in self.USER_KANJI_AREAS_SJIS:
      self.gaiji_areas[area] = ''

    self.Network = Network
    self.c1 = b'\xec' # Shift JIS

    self.Network._raw(b'\x1c\x26')           # 漢字モード指定
    self.Network._raw(b'\x1c\x43' + b'\x01') # 漢字コード指定(Shitf JIS)

    self.__LoadJISCharacterSet()

# Thanks! https://github.com/nakamura001/JIS_CharacterSet
# ※チルダがオーバーラインになっている
  def __LoadJISCharacterSet(self):
    self.jis_x_0201 = []
    self.jis_x_0208 = []
    self.jis_x_0212 = []
    self.jis_x_0213 = []

    with open("JIS0201.TXT","r") as f:
      for row in f:
        if row[0] != '#':
          c = row.split("\t")[1]
          self.jis_x_0201.append(chr(int(c, 16)))

    with open("JIS0208.TXT","r") as f:
      for row in f:
        if row[0] != '#':
          c = row.split("\t")[2]
          self.jis_x_0208.append(chr(int(c, 16)))

    with open("JIS0212.TXT","r") as f:
      for row in f:
        if row[0] != '#':
          c = row.split("\t")[1]
          self.jis_x_0212.append(chr(int(c, 16)))

    with open("JIS0213-2004.TXT","r") as f:
      for row in f:
        if row[0] != '#':
          c = row.split("\t")[1]
          self.jis_x_0213.append(chr(int(c, 16)))

  def __EscposRegisterGaiji(self, c2, gaiji, font, size, adjustX, adjustY, asciiflg):
    """ESC/POSコマンドによる外字の登録

    :param c2:      外字の文字コードの第2バイト
    :param gaiji:   外字
    :param font:    外字フォント
    :param size:    フォントサイズ
    :param adjustX: フォント描画位置調節x軸(ピクセル)
    :param adjustY: フォント描画位置調節x軸(ピクセル)
    :param asciiflg: ダウンロード文字定義フラグ
    """
    if asciiflg:
      img = Image.new ('RGB', (12,24), (255,255,255))
    else:
      img = Image.new ('RGB', (24,24), (255,255,255))
    draw = ImageDraw.Draw(img)
    f = ImageFont.truetype(font, size, encoding='unic')
    draw.text((adjustX,adjustY), gaiji, fill=(0,0,0), font=f)
    img = img.convert('1')

    byte_array = []
    bit_str = ''
    for x in range(img.width):
      for y in range(img.height):
        pixel = img.getpixel((x,y))
        if pixel == 255:
          bit_str += '0'
        else:
          bit_str += '1'

        if not (y + 1) % 8:
          byte_array.append(int(bit_str, 2).to_bytes(1, 'big'))
          bit_str = ''

    if asciiflg:
      self.Network._raw(b'\x1b\x26\x03' + c2 + c2)  # ESC &
      self.Network._raw(b'\x0c')
    else:
      self.Network._raw(b'\x1c\x32' + self.c1 + c2) # FS 2

    for byte in byte_array:
      self.Network._raw(byte)

  def __DefineGaiji(self, gaiji, font="C:/Windows/Fonts/SEGUIEMJ.TTF", size=18, adjustX=0, adjustY=0, asciiflg=False):
    """外字の登録

    :param gaiji:    外字文字
    :param font:     外字フォント
    :param size:     フォントサイズ
    :param adjustX:  フォント描画位置調節x軸(ピクセル)
    :param adjustY:  フォント描画位置調節y軸(ピクセル)
    :param asciiflg: ダウンロード文字定義フラグ
    """
    # ダウンロード文字
    if asciiflg:
      for k, v in self.user_areas.items():
        if v == gaiji:
          self.user_areas[k] = self.user_areas.pop(k) # 削除して追加
          return b'\x1b\x25\x01' + k + b'\x1b\x25\x00'

      for k, v in self.user_areas.items():
        self.user_areas.pop(k)
        self.user_areas[k] = gaiji

        self.__EscposRegisterGaiji(k,gaiji,font,size,adjustX,adjustY,asciiflg) # 定義または再定義
        return b'\x1b\x25\x01' + k + b'\x1b\x25\x00'

    # 外字
    else:
      for k, v in self.gaiji_areas.items():
        if v == gaiji:
          self.gaiji_areas[k] = self.gaiji_areas.pop(k) # 削除して追加
          return self.c1 + k

      for k, v in self.gaiji_areas.items():
        self.gaiji_areas.pop(k)
        self.gaiji_areas[k] = gaiji

        self.__EscposRegisterGaiji(k,gaiji,font,size,adjustX,adjustY,asciiflg) # 定義または再定義
        return self.c1 + k

    return b''

  def jptext2(self, text):
    """外字対応テキスト出力(暫定)

    :param text: テキスト
    """
    binary_str = b''
    for c in text:
      is_emoji   = c in emoji.unicode_codes.UNICODE_EMOJI['en']
      is_jis0201 = c in self.jis_x_0201
      is_jis0208 = c in self.jis_x_0208
      is_jis0212 = c in self.jis_x_0212
      is_jis0213 = c in self.jis_x_0213

      if is_emoji:
        binary_str = self.__DefineGaiji(c,font='seguiemj.ttf',adjustY=4)
      elif is_jis0212 or is_jis0213:
        binary_str = self.__DefineGaiji(c,font='NotoSansJP-Medium.otf',size=24,adjustY=-8)
      elif c.isascii() or is_jis0201 or is_jis0208:
        binary_str = c.encode('cp932','ignore')
      else:
#        binary_str = self.__DefineGaiji(c,font='NotoSansJP-Medium.otf',size=24,adjustY=-8)
#        binary_str = self.__DefineGaiji(c,font='unifont_jp-14.0.01.ttf',size=16,adjustX=-2,adjustY=4,asciiflg=True)
        binary_str = self.__DefineGaiji(c,font='unifont_jp-14.0.01.ttf',size=24,adjustX=2,adjustY=0,asciiflg=False)

      self.Network._raw(binary_str)

# ------------------------------
p = Network("192.168.10.21")
p2 = Gaiji(p)
p2.jptext2("文字出力テスト\n")
p2.jptext2("abcABCあ*アア\\~|①②㍑〶㌧㌦\n")
p2.jptext2("絵文字 :🅱♨🆖👍🐕🛰\n")
p2.jptext2("JIS0208:亜腕亞熙\n")
p2.jptext2("JIS0212:丂侄黸龥\n")
p2.jptext2("JIS0213-2004:俱剝瘦繫\n")
p2.jptext2("外字登録😁なので文字の途中👍👍で使えます🛰\n")
p2.jptext2("\n")
p2.jptext2("ハングル:모든 인류 구성원의 천부의 존엄성과 동등하고 양도할 수 없는 권리를 인정하는\n")
p2.jptext2("繁体字:鑑於對人類家庭所有成員的固有尊嚴及其平等的和不移的權利的承認,乃是世界自由、正義與和平的基礎\n")
p2.jptext2("簡体字:鉴于对人类家庭所有成员的固有尊严及其平等的和不移的权利的承认,乃是世界自由、正义与和平的基础\n")
p2.jptext2("ベンガル文字:যেহেতু মানব পরিবারের সকল সদস্যের সমান ও অবিচ্ছেদ্য অধিকারসমূহ\n")
p.cut()

残念ながらアラビア語は対応予定はないです。

課題

  • ハングル、繁体字、簡体字を指定フォントで(unifontは使わない)
タイトルとURLをコピーしました