263 lines
9.3 KiB
Python
263 lines
9.3 KiB
Python
#!/bin/python
|
|
"""
|
|
A module for generating A5 size pdf zines
|
|
based on pyFPDF.
|
|
GPL3 License, Mara Karagianni May 2021
|
|
"""
|
|
import glob
|
|
import random
|
|
import re
|
|
import subprocess
|
|
from fpdf import FPDF
|
|
# ref https://pyfpdf.readthedocs.io/en/latest/
|
|
|
|
|
|
class Zine(FPDF):
|
|
|
|
def add_new_signature(self, top_margin, left_margin, right_margin):
|
|
# create new page/signature
|
|
self.add_page()
|
|
self.set_margins(left_margin, top_margin, right_margin)
|
|
self.set_xy(left_margin, top_margin)
|
|
print('NEW SIGNATURE')
|
|
|
|
def move_to_page_right(self, top_margin, left_max_margin, right_margin):
|
|
print('*****')
|
|
print("BOTTOM OF LEFT PAGE, height is {}".format(self.get_y()))
|
|
print('*****')
|
|
self.set_margins(top_margin, left_max_margin, right_margin)
|
|
self.set_xy(left_max_margin, top_margin)
|
|
|
|
def position_img(self, img_filename, img_x, img_y, **kwargs):
|
|
img_size = subprocess.run(
|
|
["identify", "-format", "%[fx:w/150] by %[fx:h/150] inches",
|
|
"%s" % img_filename],
|
|
stdout=subprocess.PIPE, text=True)
|
|
|
|
img_height_inches = img_size.stdout.split(' ')[2]
|
|
img_width_inches = img_size.stdout.split(' ')[0]
|
|
img_height_mm = float(img_height_inches) * float(24.5)
|
|
img_width_mm = float(img_width_inches) * float(24.5)
|
|
|
|
if kwargs:
|
|
max_height = kwargs["max_height"]
|
|
left_margin = kwargs["left_margin"]
|
|
top_margin = kwargs["top_margin"]
|
|
|
|
if self.get_y() + img_height_mm >= max_height:
|
|
self.add_page()
|
|
self.set_xy(left_margin, top_margin)
|
|
img_y = top_margin
|
|
|
|
previous_y = self.get_y()
|
|
# center image
|
|
img_x = (150 - img_width_mm) / 2
|
|
self.image(img_filename, img_x, img_y, img_width_mm)
|
|
|
|
# move y at the bottom of the image
|
|
# TODO check if get_y() would do the same job
|
|
self.set_xy(self.get_x(), previous_y+img_height_mm)
|
|
|
|
def shuffle_chapters(self, pdfinput):
|
|
# TODO add 2 blank pages after the cover and colophon
|
|
# check if we have an odd number of pages
|
|
subprocess.run(
|
|
["pdftk", "%s" % pdfinput, "burst", "output", "./%02d_chapter.pdf"],
|
|
stdout=subprocess.PIPE, text=True)
|
|
pages = glob.glob("./*_chapter.pdf")
|
|
pages.sort()
|
|
print("CHAPTERS {}".format(pages))
|
|
shuffled_list = []
|
|
count = 0
|
|
while count < (len(pages))/2:
|
|
shuffled_list.append(pages[-(count+1)])
|
|
shuffled_list.append(pages[count])
|
|
count += 1
|
|
# reverse
|
|
if count != len(pages)/2:
|
|
shuffled_list.append(pages[count])
|
|
shuffled_list.append(pages[-(count+1)])
|
|
count += 1
|
|
return shuffled_list
|
|
|
|
def create_pages(self, filename, max_height, left_margin,
|
|
left_max_margin, top_margin, right_margin, *args):
|
|
if args:
|
|
cell_width = args[0]
|
|
cell_default_height = args[1]
|
|
cell_header_height = args[2]
|
|
header_font = args[3]
|
|
english_font = args[4]
|
|
chinese_font = args[5]
|
|
korean_font = args[6]
|
|
default_font_size = args[7]
|
|
|
|
f = open(filename, 'rt')
|
|
lines = f.readlines()
|
|
|
|
# first page
|
|
print("FIRST PAGE")
|
|
self.set_margins(left_margin, top_margin, right_margin)
|
|
self.set_xy(left_margin, top_margin)
|
|
self.add_page()
|
|
text_font = None
|
|
text_font_size = None
|
|
|
|
for line in lines:
|
|
position = 'L'
|
|
|
|
if re.search(u'[\u4e00-\u9fff]', line):
|
|
text_font = chinese_font
|
|
elif re.search(u'[\uac00-\ud7af]', line):
|
|
text_font = korean_font
|
|
else:
|
|
text_font = english_font
|
|
# check if we have an image
|
|
if line.startswith("<img>"):
|
|
img_filename = line.split("<img>")[1]
|
|
img_path = img_filename.split(".")[-2]
|
|
img_name = img_path.split("/")[-1]
|
|
kwargs = {
|
|
"max_height": max_height,
|
|
"left_margin": left_margin,
|
|
"top_margin": top_margin
|
|
}
|
|
self.position_img(
|
|
img_filename, self.get_x(), self.get_y(), **kwargs)
|
|
line = re.sub('^<img>[\w|\W]+\..+$', img_name, line)
|
|
line = re.sub('<img>', '', line)
|
|
position = 'C'
|
|
|
|
elif line.startswith("<caption>"):
|
|
line = re.sub('<caption>', '', line)
|
|
line = re.sub('<caption>', '', line)
|
|
position = 'C'
|
|
|
|
elif line.startswith("# "):
|
|
#insert a new page in the zine
|
|
if self.get_y() > top_margin:
|
|
self.set_xy(left_margin, top_margin+9)
|
|
self.add_page()
|
|
|
|
text_font_size = 32
|
|
pink_shades = random.randrange(60, 150, 20)
|
|
self.set_text_color(255, pink_shades, pink_shades)
|
|
print('1#', text_font_size)
|
|
|
|
elif line.startswith("<newpage>"):
|
|
line = re.sub('<newpage>', '', line)
|
|
#insert a new page in the zine
|
|
if self.get_y() > top_margin:
|
|
self.set_xy(left_margin, top_margin+9)
|
|
self.add_page()
|
|
|
|
elif line.startswith("## "):
|
|
line = re.sub('()', '', line)
|
|
text_font_size = 20
|
|
#gray_shades = random.randrange(0, 256, 60)
|
|
self.set_text_color(0, 255, 0)
|
|
print('two #', text_font_size)
|
|
|
|
elif line.startswith("### "):
|
|
line = re.sub('()', '', line)
|
|
text_font_size = 13
|
|
self.set_text_color(255, 0, 0)
|
|
print('three #', text_font_size)
|
|
|
|
elif line.startswith("`") or line.startswith("```"):
|
|
self.set_text_color(0, 30, 255)
|
|
line = re.sub('((`)|(```))', '', line)
|
|
|
|
else:
|
|
text_font_size = default_font_size
|
|
|
|
variable_x = self.get_x()
|
|
self.set_font(text_font, '', size=text_font_size)
|
|
# self.multi_cell(cell_width, cell_default_height, line, 0, align='L')
|
|
self.multi_cell(cell_width, cell_default_height, line, 0, align=position)
|
|
self.set_xy(variable_x, self.get_y())
|
|
# go back to text font
|
|
self.set_text_color(0, 0, 0)
|
|
self.set_font(size=default_font_size)
|
|
|
|
# close file
|
|
f.close()
|
|
# self.footer()
|
|
|
|
def cover(self, file_title, cover_font, max_height):
|
|
col = 10
|
|
margin = 5
|
|
self.set_margins(margin, margin, margin)
|
|
self.add_page()
|
|
try:
|
|
title = open(file_title, 'r')
|
|
except Exception as e:
|
|
print(e, "Make sure the path and the file exists!", end="\n")
|
|
else:
|
|
for line in title.readlines():
|
|
for letter in line:
|
|
if letter.isspace():
|
|
col += 40
|
|
self.set_xy(margin+col, margin)
|
|
|
|
if self.get_y() >= max_height:
|
|
self.set_xy(margin+col, margin)
|
|
col += 40
|
|
size = random.randrange(16, 30, 5)
|
|
print(size)
|
|
self.set_font(cover_font, '', size)
|
|
self.set_text_color(255, 0, 0)
|
|
variable_x = margin+col
|
|
|
|
self.set_xy(variable_x, self.get_y())
|
|
|
|
self.cell(size, size, letter)
|
|
#self.line(size, size, self.get_x(), self.get_y())
|
|
if (size % 2 == 0):
|
|
var = "D"
|
|
else:
|
|
var = "DF" # fills with color the shapes
|
|
R = random.randrange(0, 255, 40)
|
|
G = random.randrange(0, 255, 55)
|
|
B = random.randrange(0, 155, 50)
|
|
self.set_fill_color(R, G, B)
|
|
print(var)
|
|
|
|
self.rect( # draw boxes
|
|
float(self.get_x()), float(self.get_y()),
|
|
float(size/2), float(size/2), style=var)
|
|
|
|
self.circle( # draw circles
|
|
float(self.get_x()+ size/2), float(self.get_y()+ size/2),
|
|
float(size), style=var)
|
|
self.ln(size/2)
|
|
|
|
# close the file
|
|
title.close()
|
|
self.set_text_color(0, 0, 0)
|
|
|
|
def colophon(self, text, colophon_font):
|
|
f = open(text, 'r')
|
|
lines = f.readlines()
|
|
top_margin = 20
|
|
margin = 25
|
|
self.set_margins(margin, top_margin, margin)
|
|
size = 13
|
|
self.set_font(colophon_font, '', size)
|
|
self.set_text_color(0, 0, 0)
|
|
self.add_page()
|
|
for line in lines:
|
|
self.multi_cell(100, size, line, 0, align='C')
|
|
# close the file
|
|
f.close()
|
|
|
|
def footer(self):
|
|
text_font = 'Helvetica'
|
|
# Go to 1.5 cm from bottom
|
|
self.set_y(-12)
|
|
self.set_text_color(0, 0, 0)
|
|
self.set_font(text_font, '', size=7)
|
|
# Print current page number
|
|
# self.cell(0, 7, '%s' % self.page_no(), 0, 0, 'C')
|
|
self.cell(0, 7, '%s' % self.page_no(), 0, 0, 'C')
|