From eab09b5483c9ad40f7bc8b00a4754fd710617c9a Mon Sep 17 00:00:00 2001 From: Yasutake Yohei <61961825+yasutakeyohei@users.noreply.github.com> Date: Tue, 22 Sep 2026 22:25:28 +0900 Subject: フロー図の印刷用PDF: ベクター生成に切り替えて軽量化 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 印刷用PDFはページ全体を1枚のラスタ画像(3100x4382px)で埋め込んでいたため、フォントのサブセット化も再圧縮も効かなかった。SVGからベクターのPDFを組み直し、同じレイアウト(2列x3行のタイル分割・余白・フッター・リンク注釈)を保ったまま、4ファイル合計11.7MBを約800KBにした。生成スクリプト scripts/make-flow-pdfs.py を追加。不要になった約1MBのPNG(ijime-judai-flow.png)は削除した。 --- .../images/ijime-judai-flow-a4-1p.pdf | Bin 2018805 -> 203166 bytes .../images/ijime-judai-flow-a4-6p.pdf | Bin 4161072 -> 206763 bytes .../images/ijime-judai-flow-private-a4-1p.pdf | Bin 1788097 -> 200717 bytes .../images/ijime-judai-flow-private-a4-6p.pdf | Bin 3734889 -> 204314 bytes .../ijime-judai-jitai/images/ijime-judai-flow.png | Bin 1038744 -> 0 bytes scripts/make-flow-pdfs.py | 110 +++++++++++++++++++++ 6 files changed, 110 insertions(+) delete mode 100644 public/ijime-judai-jitai/images/ijime-judai-flow.png create mode 100644 scripts/make-flow-pdfs.py diff --git a/public/ijime-judai-jitai/images/ijime-judai-flow-a4-1p.pdf b/public/ijime-judai-jitai/images/ijime-judai-flow-a4-1p.pdf index c1e0df2..0f90463 100644 Binary files a/public/ijime-judai-jitai/images/ijime-judai-flow-a4-1p.pdf and b/public/ijime-judai-jitai/images/ijime-judai-flow-a4-1p.pdf differ diff --git a/public/ijime-judai-jitai/images/ijime-judai-flow-a4-6p.pdf b/public/ijime-judai-jitai/images/ijime-judai-flow-a4-6p.pdf index 9141a81..4957595 100644 Binary files a/public/ijime-judai-jitai/images/ijime-judai-flow-a4-6p.pdf and b/public/ijime-judai-jitai/images/ijime-judai-flow-a4-6p.pdf differ diff --git a/public/ijime-judai-jitai/images/ijime-judai-flow-private-a4-1p.pdf b/public/ijime-judai-jitai/images/ijime-judai-flow-private-a4-1p.pdf index b84a00e..0724142 100644 Binary files a/public/ijime-judai-jitai/images/ijime-judai-flow-private-a4-1p.pdf and b/public/ijime-judai-jitai/images/ijime-judai-flow-private-a4-1p.pdf differ diff --git a/public/ijime-judai-jitai/images/ijime-judai-flow-private-a4-6p.pdf b/public/ijime-judai-jitai/images/ijime-judai-flow-private-a4-6p.pdf index 760f4c2..189442b 100644 Binary files a/public/ijime-judai-jitai/images/ijime-judai-flow-private-a4-6p.pdf and b/public/ijime-judai-jitai/images/ijime-judai-flow-private-a4-6p.pdf differ diff --git a/public/ijime-judai-jitai/images/ijime-judai-flow.png b/public/ijime-judai-jitai/images/ijime-judai-flow.png deleted file mode 100644 index 47bfc24..0000000 Binary files a/public/ijime-judai-jitai/images/ijime-judai-flow.png and /dev/null differ diff --git a/scripts/make-flow-pdfs.py b/scripts/make-flow-pdfs.py new file mode 100644 index 0000000..f6e263b --- /dev/null +++ b/scripts/make-flow-pdfs.py @@ -0,0 +1,110 @@ +"""いじめ重大事態対応フロー図の印刷用PDFを、SVGからベクターで生成する。 + +以前は 2.5 倍のラスタPNGを埋め込んだPDF(1ページ版 約2MB / 6ページ版 約4MB)を +使っていたが、同じレイアウトのままベクターで組み直し、大幅に軽量化する +(各ファイル約200KB。文字は拡大しても綺麗)。 + +- A4縦・タイル分割版(2列×3行=6ページ、のりしろ重複あり) +- A4縦・全体像1ページ版(縮小・見取り図) + +レイアウトは旧ラスタ版と同一(A4 3100x4382px 相当、余白100px、紙面2900x4182px、 +タイル 1160x1672.8、列 x=[0,660]、行 y=[0, base/2, base])。 +base は SVG の元の高さ(リンク行を追記する前の値)。SVG の末尾に追記した +解説ページへのリンク行は、PDFではフッターのリンク注釈として付ける。 + +使い方: python scripts/make-flow-pdfs.py +""" +import pathlib +import sys + +import pymupdf + +sys.stdout.reconfigure(encoding="utf-8") + +IMAGES = pathlib.Path(__file__).resolve().parent.parent / "public" / "ijime-judai-jitai" / "images" +URL = "https://yasutakeyohei.com/ijime-judai-jitai/flow/" +TITLE = "いじめの重大事態の対応フロー(ロール別)" + +# 旧ラスタ版と同じジオメトリ(A4 3100x4382px 相当) +A4W = pymupdf.paper_rect("a4").width +A4H = pymupdf.paper_rect("a4").height +PX2PT = A4W / 3100.0 +MARGIN = 100 * PX2PT +DEST = pymupdf.Rect(MARGIN, MARGIN, MARGIN + 2900 * PX2PT, MARGIN + 4182 * PX2PT) +TILE_W1 = 1160.0 # タイル幅(SVG座標=1x基準) +TILE_H1 = 1672.8 # タイル高さ +FOOT_SIZE = 50 * PX2PT # 旧: int(20*2.5)=50px +FOOT_TOP = (4382 - 100 + 15) * PX2PT +FOOT_COLOR = (0x45 / 255, 0x5A / 255, 0x64 / 255) +FOOT_6P = TITLE + " {n}/6 (全体の一部・のりしろ重複あり)" +FOOT_1P = TITLE + " 全体像(縮小のため文字は小さめ。読みやすい印刷は6ページ版を推奨)" + +# (SVGファイル名, 出力の6ページ版, 出力の1ページ版, SVGの元の高さ) +JOBS = [ + ("ijime-judai-flow.svg", "ijime-judai-flow-a4-6p.pdf", "ijime-judai-flow-a4-1p.pdf", 3890), + ("ijime-judai-flow-private.svg", "ijime-judai-flow-private-a4-6p.pdf", + "ijime-judai-flow-private-a4-1p.pdf", 3624), +] + + +def one_page_rect(base_h): + """1ページ版の配置(旧スクリプトの縮小計算を再現)。""" + sc = min((2900 / 2.5) / 1820, ((4182 / 2.5) - 30) / base_h) + w = 1820 * sc * 2.5 * PX2PT + h = base_h * sc * 2.5 * PX2PT + x = (3100 - 1820 * sc * 2.5) * PX2PT / 2 + return pymupdf.Rect(x, MARGIN, x + w, MARGIN + h) + + +def add_footer(page, text): + page.insert_text( + pymupdf.Point(MARGIN, FOOT_TOP + FOOT_SIZE * 0.8), + text, fontsize=FOOT_SIZE, fontname="japan", color=FOOT_COLOR, + ) + page.insert_link({ + "kind": pymupdf.LINK_URI, + "from": pymupdf.Rect(0, FOOT_TOP - 5, A4W, A4H), + "uri": URL, + }) + + +def build(svg_name, out_6p, out_1p, base_h): + svg = pymupdf.open(IMAGES / svg_name) + # show_pdf_page は PDF しか受け付けないため、いったんベクターPDFに変換する + src = pymupdf.open("pdf", svg.tobytes(garbage=4, deflate=True)) + svg.close() + + xs = [0.0, 660.0] + span = base_h - TILE_H1 + ys = [0.0, float(round(span / 2)), float(span)] + + tiles = [] + n = 0 + for y in ys: + for x in xs: + n += 1 + tiles.append((pymupdf.Rect(x, y, x + TILE_W1, y + TILE_H1), FOOT_6P.format(n=n))) + tiles.append((pymupdf.Rect(0, 0, 1820, base_h), FOOT_1P)) + + def make(pages, path): + out = pymupdf.open() + for i, (clip, footer) in enumerate(pages): + page = out.new_page(width=A4W, height=A4H) + dest = DEST if i < 6 else one_page_rect(base_h) + page.show_pdf_page(dest, src, 0, clip=clip) + add_footer(page, footer) + out.subset_fonts() + tmp = path.with_suffix(".tmp.pdf") + out.save(tmp, garbage=4, deflate=True, clean=True) + out.close() + tmp.replace(path) + print(f"{path.name}: {path.stat().st_size:,} bytes") + + make(tiles[:6], IMAGES / out_6p) + make(tiles[6:], IMAGES / out_1p) + + src.close() + + +for svg_name, out_6p, out_1p, base_h in JOBS: + build(svg_name, out_6p, out_1p, base_h) -- cgit v1.3.1