2021 advent calendar day 10,11

Define user-defined characters

全モデルにはダウンロード文字の定義コマンドが存在する。
更に日本モデル(他に中国、韓国モデル)には漢字コマンドで外字機能がある。

つまり絵文字を外字登録すれば良いのでは?

ということでやってみる(今回はescposjpは使用しない)
暫定版

from escpos.printer import Network
from PIL import Image, ImageDraw, ImageFont
import emoji

class Gaiji():

  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, emojifont='C:/Windows/Fonts/SEGUIEMJ.TTF'):
    """

    :param Network:   ネットワークプリンタークラス
    :param emojifont: 絵文字フォント
    """
    self.gaiji_areas = []
    for area in self.USER_KANJI_AREAS_SJIS:
      self.gaiji_areas.append([area,'',0,0])

    self.Network = Network
    self.emojifont = emojifont

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

  def __EscposRegisterUserKanji(self, hex, kanji):
    """ESC/POSコマンドによる外字の登録(暫定)

    :param hex   定義域のアドレス
    :param kanji 外字
    """
    img_kanji = Image.new ('RGB', (24,24), (255,255,255))
    draw = ImageDraw.Draw(img_kanji)
    font = ImageFont.truetype(self.emojifont, 18, encoding='unic')
    draw.text((0,+4), kanji, fill=(0,0,0), font=font)
    img_kanji = img_kanji.convert('1')

    byte_array = []
    bit_str = ''
    for x in range(img_kanji.width):
      for y in range(img_kanji.height):
        pixel = img_kanji.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 = ''

    self.Network._raw(b'\x1C\x32\xec' + hex) # FS 2 ECh 40h-7Eh, 80h-9Eh
    for byte in byte_array:
      self.Network._raw(byte)

  def __DefineUserKanji(self, kanji):
    """外字の登録(暫定)

    ※外字領域を使い切ると登録できません

    :param kanji: 外字
    """
    for i in range(len(self.gaiji_areas)):
      if self.gaiji_areas[i][1] == '':
        self.gaiji_areas[i][1] = kanji
        self.__EscposRegisterUserKanji(self.gaiji_areas[i][0], kanji)

      if self.gaiji_areas[i][1] == kanji:
        self.gaiji_areas[i][2] += 1
        return b'\xec' + self.gaiji_areas[i][0]

    return b''

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

    :param テキスト
    """
    binary_str = b''
    for c in text:
      is_emoji = c in emoji.unicode_codes.UNICODE_EMOJI['en']
      if is_emoji:
        binary_str += self.__DefineUserKanji(c)
      else:
        binary_str += c.encode('cp932','ignore')

    self.Network._raw(binary_str)

# ------------------------------
p = Network("192.168.10.21")
p2 = Gaiji(p,'seguiemj.ttf')
p2.jptext2("絵文字テスト\n")
p2.jptext2("🍄🗻😁👍🐕🛰\n")
p2.jptext2("外字登録😁なので文字の途中👍👍で使えます🛰\n")
p.cut()

勝ったなガハハ!


ちなみに
TM-T88IVの仕様

最新っぽいTM-m30Ⅱ-Hの仕様

TM-T88IVはJIS90なのがきっつい…新しいのは流石にUTF-8辺りにも対応してるしJIS2004も万全!

ツイッターは多言語なのでJIS X 0213:2004の追加文字も、他の文字も外字登録し出力すれば色々と回避は出来そうだ(全言語に対応したフォントが必要だけど)

ということで、外字領域を上手く使う必要が出てきた。
キャッシュアルゴリズム?LFU辺りでそこら辺実装する必要がある。

タイトルとURLをコピーしました