Module: VivlioStarter::CLI::PreProcessCommands::TalkAvatarGenerator

Defined in:
lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb

Overview

簡易アバターの自動生成

Defined Under Namespace

Classes: AvatarTools

Constant Summary collapse

REL_BASE =

生成物の出力先サブディレクトリ(images/ 配下)。

'talk-avatars'
EDGE =

生成画像の一辺(px)。表示は 12mm 程度なので印刷解像度に対して十分な余裕がある。

400
POINTSIZE =

1 文字を中央に置くときの文字サイズ。

200
FONT_REL =

同梱フォント(stylesheets/ からの相対)。

'fonts/Zen_Kaku_Gothic_New/ZenKakuGothicNew-Bold.ttf'
LIGHT_BG_THRESHOLD =

地色がこれより明るければ文字を濃色にする(WCAG 相対輝度)。 yellow(#f0a000)=0.47 / lime(#65a30d)=0.30 / purple(#7c3aed)=0.14 の実測から、 白抜きが苦しくなる手前の 0.45 を境にする。

0.45
LIGHT_TEXT =
'#ffffff'
DARK_TEXT =
'#333333'

Class Method Summary collapse

Class Method Details

.avatar_glyph(char) ⇒ Object

表示名の 1 文字目。書記素クラスタ単位で取るため、絵文字や結合文字を割らない。



96
97
98
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 96

def avatar_glyph(char)
  (char&.name.to_s.strip.grapheme_clusters.first || '').to_s
end

.background_hex(char) ⇒ Object

地色。話者の color 未指定なら本のテーマ色を使う(PDF の --talk-accent 既定と一致)。



101
102
103
104
105
106
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 101

def background_hex(char)
  raw = char&.color
  return ThemeColor.to_hex6(raw) unless raw.to_s.strip.empty?

  theme_hex
end

.cache_key(glyph, background, foreground) ⇒ Object

内容アドレス。文字・色・寸法・フォントが同じなら再生成しない。



120
121
122
123
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 120

def cache_key(glyph, background, foreground)
  payload = ['v1', glyph, background, foreground, EDGE, POINTSIZE, FONT_REL].join('|')
  Digest::SHA256.hexdigest(payload)[0, 16]
end

.default_toolsObject



128
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 128

def default_tools = (@default_tools ||= AvatarTools.new)

.font_pathObject

同梱フォントの実体パス。



126
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 126

def font_path = File.join(Common.stylesheets_dir, FONT_REL)

.foreground_hex(background) ⇒ Object

地色に載せて読める文字色を選ぶ(明るい地には濃色、暗い地には白)。



115
116
117
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 115

def foreground_hex(background)
  ThemeColor.luminance(background) > LIGHT_BG_THRESHOLD ? DARK_TEXT : LIGHT_TEXT
end

.generate(char, source_filename:, tools: default_tools) ⇒ String?

話者の簡易アバターを生成し、章 HTML から参照するパスを返す。

Parameters:

  • char (TalkRegistry::Character)

    話者(name と color を使う)

  • source_filename (String)

    警告に添える原稿ファイル名

  • tools (#available?, #render) (defaults to: default_tools)

    外部ツール(テスト差し替え用)

Returns:

  • (String, nil)

    参照パス(生成できなければ nil)



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 67

def generate(char, source_filename:, tools: default_tools)
  glyph = avatar_glyph(char)
  return nil if glyph.empty?

  background = background_hex(char)
  foreground = foreground_hex(background)
  key = cache_key(glyph, background, foreground)

  unless tools.available?
    warn_tools_missing(source_filename)
    return nil
  end

  out_dir = File.join(Common::BUILD_HTML_DIR, 'images', REL_BASE)
  return nil unless write_asset!(key, out_dir, glyph:, background:, foreground:, tools:)

  "images/#{REL_BASE}/#{key}.webp"
end

.theme_hexObject

本のテーマ色(未設定・プロジェクト外では ThemeColor の既定)。



109
110
111
112
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 109

def theme_hex
  raw = Common.configured? ? Common::CONFIG.theme.color : nil
  ThemeColor.to_hex6(raw)
end

.warn_tools_missing(source_filename) ⇒ Object



130
131
132
133
134
135
136
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 130

def warn_tools_missing(source_filename)
  Common.log_warn(
    "[talk] #{source_filename}: ImageMagick が見つからないため簡易アバターを生成できません。" \
    'アバターなしで表示します',
    detail: '→ `vs doctor --fix` で導入できます(brew install imagemagick)'
  )
end

.write_asset!(key, out_dir, glyph:, background:, foreground:, tools:) ⇒ Boolean

生成物をワークスペースへ用意する(永続キャッシュ経由)。

Returns:

  • (Boolean)

    参照可能な生成物が揃ったか



88
89
90
91
92
93
# File 'lib/vivlio_starter/cli/pre_process/talk_avatar_generator.rb', line 88

def write_asset!(key, out_dir, glyph:, background:, foreground:, tools:)
  GeneratedAssetCache.fetch(REL_BASE, ["#{key}.webp"], out_dir:) do |cache_dir|
    tools.render(File.join(cache_dir, "#{key}.webp"),
                 glyph:, background:, foreground:, font: font_path)
  end
end