Module: VivlioStarter::CLI::Build::NombreStamper
- Defined in:
- lib/vivlio_starter/cli/build/nombre_stamper.rb
Constant Summary collapse
- MM_TO_PT =
Units::PT_PER_MM
- FONT_SIZE =
6- NOMBRE_FONT_RELATIVE =
隠しノンブルに使う埋め込み可能フォント(TTF)。 Prawn の標準 14 フォント 'Helvetica' は PDF に埋め込まれず、印刷所入稿で 「非埋め込みフォント」事故になる(FT-02)。同梱の HackGen35ConsoleNF(TTF)を 使えば Prawn が使用グリフ(数字のみ)をサブセット埋め込みするため極小で済む。
File.join('stylesheets', 'fonts', 'hackgen35', 'HackGen35ConsoleNF-Regular.ttf')
Class Method Summary collapse
-
.bleed_mm_from_config ⇒ Float
塗り足し幅を book.yml から取得する(mm 単位の数値を返す) "3mm" → 3.0, "5mm" → 5.0, nil → 3.0.
-
.create_nombre_pdf!(output_path, source_pdf, bleed_pt) ⇒ Object
対象 PDF と同じページ数・同じページサイズで、ノンブルだけを描いた PDF を生成する。 ページサイズを 1 ページずつ元 PDF から読み取るのは、空白ページ挿入や 前付・奥付の混在でページサイズが揃わない場合にも重畳位置をずらさないため。.
-
.draw_page_number(pdf, page_number, width, height, bleed_pt) ⇒ Object
個別ページにノンブルを描画する 奇数ページ(右ページ)はノド側 = 左端、偶数ページ(左ページ)はノド側 = 右端.
-
.draw_rotated_text(pdf, text, x:, y:, angle:) ⇒ Object
テキストを回転して描画する(translate → rotate → draw_text).
-
.nombre_font ⇒ String
隠しノンブルのフォントを解決する。 プロジェクト(cwd)→ gem 同梱 の順に同梱 TTF を探し、いずれも無ければ 'Helvetica'(非埋め込み)へフォールバックして従来どおりビルドは継続する。.
-
.parse_bleed_mm(raw) ⇒ Float
塗り足し文字列を mm 数値に変換する.
-
.stamp!(pdf_path, bleed_mm: 3) ⇒ Boolean
入稿用 PDF に隠しノンブルを書き込む 結合済み PDF のすべてのページに通し番号(1〜N)を付与する。.
Class Method Details
.bleed_mm_from_config ⇒ Float
塗り足し幅を book.yml から取得する(mm 単位の数値を返す) "3mm" → 3.0, "5mm" → 5.0, nil → 3.0
158 159 160 161 |
# File 'lib/vivlio_starter/cli/build/nombre_stamper.rb', line 158 def bleed_mm_from_config raw = Common::CONFIG.output.print_pdf.bleed parse_bleed_mm(raw) end |
.create_nombre_pdf!(output_path, source_pdf, bleed_pt) ⇒ Object
対象 PDF と同じページ数・同じページサイズで、ノンブルだけを描いた PDF を生成する。 ページサイズを 1 ページずつ元 PDF から読み取るのは、空白ページ挿入や 前付・奥付の混在でページサイズが揃わない場合にも重畳位置をずらさないため。
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
# File 'lib/vivlio_starter/cli/build/nombre_stamper.rb', line 95 def create_nombre_pdf!(output_path, source_pdf, bleed_pt) reader = ::PDF::Reader.new(source_pdf) font = nombre_font Prawn::Document.generate(output_path, skip_page_creation: true, margin: 0) do |pdf| reader.pages.each_with_index do |page, idx| box = page.attributes[:MediaBox] || [0, 0, 595.28, 841.89] width = box[2].to_f - box[0].to_f height = box[3].to_f - box[1].to_f pdf.start_new_page(size: [width, height], margin: 0) # フォントはページ作成後に設定する(skip_page_creation のため最初のページ前は不可)。 # 数字のみのため TTF はサブセット埋め込みされ極小で済む。 pdf.font(font, size: FONT_SIZE) pdf.fill_color('000000') draw_page_number(pdf, idx + 1, width, height, bleed_pt) end end end |
.draw_page_number(pdf, page_number, width, height, bleed_pt) ⇒ Object
個別ページにノンブルを描画する 奇数ページ(右ページ)はノド側 = 左端、偶数ページ(左ページ)はノド側 = 右端
127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/vivlio_starter/cli/build/nombre_stamper.rb', line 127 def draw_page_number(pdf, page_number, width, height, bleed_pt) x_offset = bleed_pt / 2.0 y_center = height / 2.0 text = page_number.to_s if page_number.odd? # 右ページ → ノド = 左端、時計回り 90° draw_rotated_text(pdf, text, x: x_offset, y: y_center, angle: 90) else # 左ページ → ノド = 右端、反時計回り -90° draw_rotated_text(pdf, text, x: width - x_offset, y: y_center, angle: -90) end end |
.draw_rotated_text(pdf, text, x:, y:, angle:) ⇒ Object
テキストを回転して描画する(translate → rotate → draw_text)
142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/vivlio_starter/cli/build/nombre_stamper.rb', line 142 def draw_rotated_text(pdf, text, x:, y:, angle:) text_width = pdf.width_of(text) text_height = pdf.font.height pdf.save_graphics_state do pdf.translate(x, y) pdf.rotate(angle) do pdf.draw_text(text, at: [-text_width / 2.0, -text_height / 2.0]) end end end |
.nombre_font ⇒ String
隠しノンブルのフォントを解決する。 プロジェクト(cwd)→ gem 同梱 の順に同梱 TTF を探し、いずれも無ければ 'Helvetica'(非埋め込み)へフォールバックして従来どおりビルドは継続する。
120 121 122 123 |
# File 'lib/vivlio_starter/cli/build/nombre_stamper.rb', line 120 def nombre_font gem_bundled = File.(File.join('../../../..', NOMBRE_FONT_RELATIVE), __dir__) [NOMBRE_FONT_RELATIVE, gem_bundled].find { File.exist?(it) } || 'Helvetica' end |
.parse_bleed_mm(raw) ⇒ Float
塗り足し文字列を mm 数値に変換する
166 167 168 169 170 171 172 173 174 |
# File 'lib/vivlio_starter/cli/build/nombre_stamper.rb', line 166 def parse_bleed_mm(raw) case raw in NilClass then 3.0 in Numeric => n then n.to_f in String => s s.strip.downcase.sub(/mm\z/, '').to_f.then { it.positive? ? it : 3.0 } else 3.0 end end |
.stamp!(pdf_path, bleed_mm: 3) ⇒ Boolean
入稿用 PDF に隠しノンブルを書き込む 結合済み PDF のすべてのページに通し番号(1〜N)を付与する。
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/vivlio_starter/cli/build/nombre_stamper.rb', line 57 def stamp!(pdf_path, bleed_mm: 3) # --- Phase: 検証 --- unless File.exist?(pdf_path) Common.log_warn("[NombreStamper] PDF が見つかりません: #{pdf_path}") return false end total_pages = Build::Utilities.page_count(pdf_path).to_i return false unless total_pages.positive? # --- Phase: ノンブル PDF の生成(Prawn) --- Common.log_action("[NombreStamper] 隠しノンブルを書き込みます(#{total_pages} ページ)…") nombre_pdf = "#{pdf_path}.nombre.pdf" create_nombre_pdf!(nombre_pdf, pdf_path, bleed_mm.to_f * MM_TO_PT) # --- Phase: 重畳(qpdf・構造保存・等倍) --- success = Build::QpdfOverlay.apply!(pdf_path, nombre_pdf) FileUtils.rm_f(nombre_pdf) if success Common.log_success("[NombreStamper] 隠しノンブル書き込み完了(#{total_pages} ページ)") else Common.log_error('[NombreStamper] 隠しノンブルの重畳(qpdf --overlay)に失敗しました') end success rescue StandardError => e Common.log_error("[NombreStamper] 隠しノンブル書き込みに失敗: #{e.}") FileUtils.rm_f("#{pdf_path}.nombre.pdf") false end |