#!/bin/bash
# Build The Bella Times PDF from the editable layout, then shrink the photos so it emails to the Brother printer.
# Usage: ./build.sh [layout/bella-times-YYYY-MM-DD.html]   (default: the newest layout file)
# Needs: Google Chrome or Chromium, python3 with PyMuPDF (pip3 install pymupdf).
# Output: pdf/<name>-print.pdf (full quality) and pdf/<name>.pdf (compressed, target under 14 MB, never 20 MB or more).
# Text and rules stay vector; photos become JPEG (quality 80) at the pixels Chrome printed, line art stays lossless.
set -euo pipefail
cd "$(dirname "$0")"
SRC="${1:-$(ls -t layout/bella-times-*.html | head -1)}"
NAME="$(basename "$SRC" .html)"
mkdir -p pdf

CHROME=""
for c in "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" google-chrome google-chrome-stable chromium chromium-browser; do
  if command -v "$c" >/dev/null 2>&1 || [ -x "$c" ]; then CHROME="$c"; break; fi
done
[ -n "$CHROME" ] || { echo "Chrome or Chromium not found"; exit 1; }

# The page's own script fits text and pins every box and picture after fonts load; the time budget lets it finish before printing.
"$CHROME" --headless=new --disable-gpu --no-sandbox --allow-file-access-from-files --no-pdf-header-footer \
  --virtual-time-budget=10000 --print-to-pdf="pdf/$NAME-print.pdf" "file://$PWD/$SRC" >/dev/null 2>&1

python3 - "pdf/$NAME-print.pdf" "pdf/$NAME.pdf" <<'PY'
import sys, fitz
src, out = sys.argv[1:]
d = fitz.open(src)
# Photos -> JPEG at the pixel size Chrome printed; black and white line art -> lossless greyscale.
# The image streams are rewritten in place so Chrome's soft masks (thin see through edges) stay attached.
# Anything substantially see through (the kiss mark) and small images are left exactly as they are.
def set_image(x, data, cs, flt):
    d.update_stream(x, data, compress=(flt == 'FlateDecode'))
    d.xref_set_key(x, 'Filter', '/' + flt); d.xref_set_key(x, 'ColorSpace', '/' + cs)
    d.xref_set_key(x, 'BitsPerComponent', '8'); d.xref_set_key(x, 'DecodeParms', 'null')
done = set()
for page in d:
    for im in page.get_images(full=True):
        x, smask = im[0], im[1]
        if x in done: continue
        done.add(x)
        if len(d.xref_stream_raw(x)) < 150_000: continue
        if smask:
            a = fitz.Pixmap(d, smask).samples
            if sum(1 for v in a[::5] if v < 250) / len(a[::5]) > 0.10: continue
        pix = fitz.Pixmap(d, x)
        if pix.alpha: pix = fitz.Pixmap(pix, 0)
        if pix.colorspace.n != 3: pix = fitz.Pixmap(fitz.csRGB, pix)
        g = fitz.Pixmap(fitz.csGRAY, pix)
        gs, rgb = g.samples, pix.samples
        ends = sum(1 for v in gs[::7] if v < 40 or v > 215) / len(gs[::7])
        tint = max(abs(rgb[i] - rgb[i + 1]) + abs(rgb[i + 1] - rgb[i + 2]) for i in range(0, len(rgb) - 3, 3 * 101))
        if ends > 0.92 and tint < 24:
            set_image(x, gs, 'DeviceGray', 'FlateDecode')  # line art: lossless, one channel
        else:
            set_image(x, pix.tobytes('jpeg', jpg_quality=80), 'DeviceRGB', 'DCTDecode')
d.save(out, garbage=4, deflate=True)
import os
a, b = os.path.getsize(src), os.path.getsize(out)
print(f"{src}: {a/1e6:.1f} MB -> {out}: {b/1e6:.1f} MB, {len(fitz.open(out))} pages")
if b >= 20_000_000: print("TOO BIG FOR THE PRINTER (20 MB limit)"); sys.exit(1)
if b >= 14_000_000: print("WARNING: over the 14 MB target")
PY
shasum -a 256 "pdf/$NAME.pdf"
