home · contact · privacy
Bookmaker: more refactoring.
authorChristian Heller <c.heller@plomlompom.de>
Sun, 24 Sep 2023 22:13:32 +0000 (00:13 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Sun, 24 Sep 2023 22:13:32 +0000 (00:13 +0200)
bookmaker.py

index d111cf18f4530379e5d75581534c89fb801568e6..2dd96532e7f8876e3f7218b88a99a6a27e75e86f 100755 (executable)
@@ -86,11 +86,11 @@ A4_HALF_HEIGHT = A4_HEIGHT / 2
 CUT_DEPTH = 1.95 * POINTS_PER_CM
 CUT_WIDTH = 1.05 * POINTS_PER_CM
 MIDDLE_POINT_DEPTH = 0.4 * POINTS_PER_CM
-SPINE_LIMIT = 1 * POINTS_PER_CM
+INNER_SPINE_MARGIN_PER_PAGE = 1 * POINTS_PER_CM
 QUARTER_SCALE_FACTOR = 0.5
 PAGE_ORDER_FOR_NUP4 = (3,0,7,4,1,2,5,6)
 
-# some helpers
+
 class PageCrop:
 
     def __init__(self, left_cm=0, bottom_cm=0, right_cm=0, top_cm=0):
@@ -130,11 +130,14 @@ class PageCrop:
         return PageCrop(left_cm=self.right_cm, bottom_cm=self.bottom_cm, right_cm=self.left_cm, top_cm=self.top_cm)
 
 
-class PrintableMargin:
+class Nup4Geometry:
 
-    def __init__(self, size_cm):
-        self.size = size_cm * POINTS_PER_CM
-        self.zoom = (A4_WIDTH - 2 * self.size)/A4_WIDTH
+    def __init__(self, margin_cm):
+        self.margin = margin_cm * POINTS_PER_CM
+        self.shrink_for_margin = (A4_WIDTH - 2 * self.margin)/A4_WIDTH
+        # NB: We define spine size un-shrunk, but .shrink_for_spine is used with values shrunk for the margin, which we undo here.
+        spine_part_of_page = (INNER_SPINE_MARGIN_PER_PAGE / A4_HALF_WIDTH) / self.shrink_for_margin
+        self.shrink_for_spine = 1 - spine_part_of_page
 
 
 class HandledException(Exception):
@@ -350,32 +353,31 @@ def build_single_pages_output(writer, pages_to_add, crop_at_page):
         odd_page = not odd_page
         print(f"built page number {i+1} (of {len(pages_to_add)})")
 
+
 def build_nup4_output(writer, pages_to_add, crop_at_page, args_print_margin, args_analyze, canvas_class):
     print("-n: building 4-input-pages-per-output-page book")
     print(f"-m: applying printable-area margin of {args_print_margin}cm")
     if args_analyze:
         print("-a: drawing page borders, spine limits")
-    printable_margin = PrintableMargin(args_print_margin)
-    spine_part_of_page = (SPINE_LIMIT / A4_HALF_WIDTH) / printable_margin.zoom
-    bonus_shrink_factor = 1 - spine_part_of_page
+    nup4_geometry = Nup4Geometry(args_print_margin)
     pages_to_add, new_i_order = resort_pages_for_nup4(pages_to_add)
-    nup4_position = 0
+    nup4_i = 0
     page_count = 0
     is_front_page = True
     for i, page in enumerate(pages_to_add):
-        if nup4_position == 0:
+        if nup4_i == 0:
             new_page = pypdf.PageObject.create_blank_page(width=A4_WIDTH, height=A4_HEIGHT)
         corrected_i = new_i_order[i]
-        nup4_inner_page_transform(page, crop_at_page[corrected_i], bonus_shrink_factor, printable_margin, nup4_position)
-        nup4_outer_page_transform(page, bonus_shrink_factor, nup4_position)
+        nup4_inner_page_transform(page, crop_at_page[corrected_i], nup4_geometry, nup4_i)
+        nup4_outer_page_transform(page, nup4_geometry, nup4_i)
         new_page.merge_page(page)
         page_count += 1
         print(f"merged page number {page_count} (of {len(pages_to_add)})")
-        nup4_position += 1
-        if nup4_position > 3:
-            ornate_nup4(writer, args_analyze, is_front_page, new_page, printable_margin, bonus_shrink_factor, canvas_class)
+        nup4_i += 1
+        if nup4_i > 3:
+            ornate_nup4(writer, args_analyze, is_front_page, new_page, nup4_geometry, canvas_class)
             writer.add_page(new_page)
-            nup4_position = 0
+            nup4_i = 0
             is_front_page = not is_front_page
 
 
@@ -399,33 +401,33 @@ def resort_pages_for_nup4(pages_to_add):
     return new_page_order, new_i_order
 
 
-def nup4_inner_page_transform(page, crop, bonus_shrink_factor, printable_margin, nup4_position):
+def nup4_inner_page_transform(page, crop, nup4_geometry, nup4_i):
     page.add_transformation(pypdf.Transformation().translate(ty=(A4_HEIGHT / crop.zoom - (A4_HEIGHT - crop.top))))
-    if nup4_position == 0 or nup4_position == 2:
+    if nup4_i == 0 or nup4_i == 2:
         page.add_transformation(pypdf.Transformation().translate(tx=-crop.left))
-    elif nup4_position == 1 or nup4_position == 3:
+    elif nup4_i == 1 or nup4_i == 3:
         page.add_transformation(pypdf.Transformation().translate(tx=(A4_WIDTH / crop.zoom - (A4_WIDTH - crop.right))))
-    page.add_transformation(pypdf.Transformation().scale(crop.zoom * bonus_shrink_factor, crop.zoom * bonus_shrink_factor))
-    if nup4_position == 2 or nup4_position == 3:
-        page.add_transformation(pypdf.Transformation().translate(ty=-2*printable_margin.size/printable_margin.zoom))
+    page.add_transformation(pypdf.Transformation().scale(crop.zoom * nup4_geometry.shrink_for_spine, crop.zoom * nup4_geometry.shrink_for_spine))
+    if nup4_i == 2 or nup4_i == 3:
+        page.add_transformation(pypdf.Transformation().translate(ty=-2*nup4_geometry.margin/nup4_geometry.shrink_for_margin))
 
 
-def nup4_outer_page_transform(page, bonus_shrink_factor, nup4_position):
-    page.add_transformation(pypdf.Transformation().translate(ty=(1-bonus_shrink_factor)*A4_HEIGHT))
-    if nup4_position == 0 or nup4_position == 1:
+def nup4_outer_page_transform(page, nup4_geometry, nup4_i):
+    page.add_transformation(pypdf.Transformation().translate(ty=(1-nup4_geometry.shrink_for_spine)*A4_HEIGHT))
+    if nup4_i == 0 or nup4_i == 1:
         y_section = A4_HEIGHT
         page.mediabox.bottom = A4_HALF_HEIGHT
         page.mediabox.top    = A4_HEIGHT
-    if nup4_position == 2 or nup4_position == 3:
+    if nup4_i == 2 or nup4_i == 3:
         y_section = 0
         page.mediabox.bottom = 0
         page.mediabox.top  =  A4_HALF_HEIGHT
-    if nup4_position == 0 or nup4_position == 2:
+    if nup4_i == 0 or nup4_i == 2:
         x_section = 0
         page.mediabox.left   = 0
         page.mediabox.right  = A4_HALF_WIDTH
-    if nup4_position == 1 or nup4_position == 3:
-        page.add_transformation(pypdf.Transformation().translate(tx=(1-bonus_shrink_factor)*A4_WIDTH))
+    if nup4_i == 1 or nup4_i == 3:
+        page.add_transformation(pypdf.Transformation().translate(tx=(1-nup4_geometry.shrink_for_spine)*A4_WIDTH))
         x_section = A4_WIDTH
         page.mediabox.left   = A4_HALF_WIDTH
         page.mediabox.right  = A4_WIDTH
@@ -433,7 +435,7 @@ def nup4_outer_page_transform(page, bonus_shrink_factor, nup4_position):
     page.add_transformation(pypdf.Transformation().scale(QUARTER_SCALE_FACTOR, QUARTER_SCALE_FACTOR))
 
 
-def ornate_nup4(writer, args_analyze, is_front_page, new_page, printable_margin, bonus_shrink_factor, canvas_class):
+def ornate_nup4(writer, args_analyze, is_front_page, new_page, nup4_geometry, canvas_class):
     if args_analyze:
         # borders
         packet = io.BytesIO()
@@ -448,11 +450,11 @@ def ornate_nup4(writer, args_analyze, is_front_page, new_page, printable_margin,
         c.save()
         new_pdf = pypdf.PdfReader(packet)
         new_page.merge_page(new_pdf.pages[0])
-    printable_offset_x = printable_margin.size
-    printable_offset_y = printable_margin.size * A4_HEIGHT / A4_WIDTH
-    new_page.add_transformation(pypdf.Transformation().scale(printable_margin.zoom, printable_margin.zoom))
+    printable_offset_x = nup4_geometry.margin
+    printable_offset_y = nup4_geometry.margin * A4_HEIGHT / A4_WIDTH
+    new_page.add_transformation(pypdf.Transformation().scale(nup4_geometry.shrink_for_margin, nup4_geometry.shrink_for_margin))
     new_page.add_transformation(pypdf.Transformation().translate(tx=printable_offset_x, ty=printable_offset_y))
-    x_left_spine_limit = A4_HALF_WIDTH * bonus_shrink_factor
+    x_left_spine_limit = A4_HALF_WIDTH * nup4_geometry.shrink_for_spine
     x_right_spine_limit = A4_WIDTH - x_left_spine_limit
     if args_analyze or is_front_page:
         packet = io.BytesIO()