From: Plom Heller Date: Fri, 10 Apr 2026 07:32:04 +0000 (+0200) Subject: Some code restructuring. X-Git-Url: https://plomlompom.com/repos/%7B%7B%20web_path%20%7D%7D/%7B%7Bdb.prefix%7D%7D/foo.html?a=commitdiff_plain;h=HEAD;p=bookmaker Some code restructuring. --- diff --git a/bookmaker.py b/bookmaker.py index 92e7a38..e43d754 100755 --- a/bookmaker.py +++ b/bookmaker.py @@ -167,7 +167,7 @@ class Page: ) -> None: 'Draw horizontal or vertical lines.' min_x, min_y, max_x, max_y = self._pypdf.mediabox - full_lines = [] + full_lines: list[tuple[float, float, float, float]] = [] for is_horizontal, position in lines: if is_horizontal: x0, x1 = min_x, max_x @@ -176,7 +176,7 @@ class Page: y0, y1 = min_y, max_y x0 = x1 = position full_lines += [(x0, y0, x1, y1)] - self.draw_lines(full_lines, rgb_color, line_width) + self.draw_lines(tuple(full_lines), rgb_color, line_width) def draw_borders( self, @@ -190,6 +190,88 @@ class Page: rgb_color, line_width) + def nup4_transforms( + self, + nup4_geometry: 'Nup4Geometry', + nup4_i: int + ) -> None: + 'Perform inner, outer page transforms to position in nup4_geometry.' + # Apply crop instructions adequate to position in nup4 geometry. + self.translate( + tx=((-self.crop.left) if nup4_i in {0, 2} + else # in {1, 3} + A4_WIDTH / self.crop.zoom - (A4_WIDTH - self.crop.right)), + ty=A4_HEIGHT / self.crop.zoom - (A4_HEIGHT - self.crop.top)) + self.scale(self.crop.zoom * nup4_geometry.shrink_for_spine) + if nup4_i in {2, 3}: + self.translate( + ty=-2 * nup4_geometry.margin / nup4_geometry.shrink_for_margin) + # Shrink and position into nup4_geometry as per its position nup4_i. + self.translate(ty=(1 - nup4_geometry.shrink_for_spine) * A4_HEIGHT) + if nup4_i in {0, 1}: + y_section = A4_HEIGHT + self.set_box(bottom=A4_HEIGHT/2, top=A4_HEIGHT) + else: # nup4_in in {2, 3} + y_section = 0 + self.set_box(bottom=0, top=A4_HEIGHT/2) + x_section: float + if nup4_i in {0, 2}: + x_section = 0 + self.set_box(left=0, right=A4_WIDTH/2) + else: # nup4_in in {1, 3} + self.translate(tx=(1 - nup4_geometry.shrink_for_spine) * A4_WIDTH) + x_section = A4_WIDTH + self.set_box(left=A4_WIDTH/2, right=A4_WIDTH) + self.translate(tx=x_section, ty=y_section) + self.scale(QUARTER_SCALE_FACTOR) + + def ornate_nup4( + self, + is_front_page: bool, + nup4_geometry: 'Nup4Geometry', + analyzing: bool + ) -> None: + 'Apply nup4 line guides.' + + def draw_book_binding_cut_guide( + x_spine_limit: float, + direction: int + ) -> None: + directed_half_width = 0.5 * CUT_WIDTH * direction + outer_start_x = x_spine_limit - directed_half_width + inner_start_x = x_spine_limit + directed_half_width + middle_point_y = A4_HEIGHT/2 + MIDDLE_POINT_DEPTH * direction + end_point_y = A4_HEIGHT/2 + CUT_DEPTH * direction + self.draw_lines(((inner_start_x, A4_HEIGHT/2, + x_spine_limit, end_point_y), + (x_spine_limit, end_point_y, + x_spine_limit, middle_point_y), + (x_spine_limit, middle_point_y, + outer_start_x, A4_HEIGHT/2)), + line_width=0.2) + + if analyzing: + self.draw_borders((0.5, 1.0, 1.0)) + self.draw_orth_lines(((True, self.box['top']/2), + (False, self.box['right']/2)), + line_width=0.1) + printable_offset_x = nup4_geometry.margin + printable_offset_y = nup4_geometry.margin * A4_HEIGHT / A4_WIDTH + self.scale(nup4_geometry.shrink_for_margin) + self.translate(tx=printable_offset_x, ty=printable_offset_y) + if not (analyzing or is_front_page): + return + x_left_spine_limit = A4_WIDTH/2 * nup4_geometry.shrink_for_spine + x_right_spine_limit = A4_WIDTH - x_left_spine_limit + if analyzing: + self.draw_orth_lines(((False, x_left_spine_limit,), + (False, x_right_spine_limit)), + line_width=0.1, + rgb_color=(1.0, 0.5, 1.0)) + if is_front_page: + draw_book_binding_cut_guide(x_left_spine_limit, 1) + draw_book_binding_cut_guide(x_right_spine_limit, -1) + class PageCrop: 'Per-page crop instructions as sizes in point and cm, and A4-zoom factor.' @@ -639,7 +721,7 @@ def build_nup4_output( writer: PdfWriter, pages: list[Page], args_print_margin: int, - arg_analyze: str, + arg_analyze: bool, ) -> None: 'Build nup4 pages from inputs.' print('-n: building 4-input-pages-per-output-page book') @@ -653,14 +735,13 @@ def build_nup4_output( is_front_page = True new_page = Page.new_blank() for page in pages: - nup4_inner_page_transform(page, nup4_geometry, nup4_i) - nup4_outer_page_transform(page, nup4_geometry, nup4_i) + page.nup4_transforms(nup4_geometry, nup4_i) new_page.merge_page(page) page_count += 1 print(f'merged page number {page_count} (of {len(pages)})') nup4_i += 1 if nup4_i > 3: - ornate_nup4(arg_analyze, is_front_page, new_page, nup4_geometry) + new_page.ornate_nup4(is_front_page, nup4_geometry, arg_analyze) new_page.add_to_writer(writer) nup4_i = 0 new_page = Page.new_blank() @@ -688,94 +769,6 @@ def resort_pages_for_nup4( pages[:] = new_page_order[:] -def nup4_inner_page_transform( - page: Page, - nup4_geometry: Nup4Geometry, - nup4_i: int - ) -> None: - 'Apply to page crop instructions adequate to position in nup4 geometry.' - page.translate(ty=A4_HEIGHT / page.crop.zoom - (A4_HEIGHT - page.crop.top)) - page.translate(tx=( - (-page.crop.left) if nup4_i in {0, 2} else - A4_WIDTH / page.crop.zoom - (A4_WIDTH - page.crop.right))) # in {1, 3} - page.scale(page.crop.zoom * nup4_geometry.shrink_for_spine) - if nup4_i in {2, 3}: - page.translate( - ty=-2 * nup4_geometry.margin / nup4_geometry.shrink_for_margin) - - -def nup4_outer_page_transform( - page: Page, - nup4_geometry: Nup4Geometry, - nup4_i: int - ) -> None: - 'Shrink and position page into nup4_geometry as per its position nup4_i.' - page.translate(ty=(1 - nup4_geometry.shrink_for_spine) * A4_HEIGHT) - if nup4_i in {0, 1}: - y_section = A4_HEIGHT - page.set_box(bottom=A4_HEIGHT/2, top=A4_HEIGHT) - else: # nup4_in in {2, 3} - y_section = 0 - page.set_box(bottom=0, top=A4_HEIGHT/2) - x_section: float - if nup4_i in {0, 2}: - x_section = 0 - page.set_box(left=0, right=A4_WIDTH/2) - else: # nup4_in in {1, 3} - page.translate(tx=(1 - nup4_geometry.shrink_for_spine) * A4_WIDTH) - x_section = A4_WIDTH - page.set_box(left=A4_WIDTH/2, right=A4_WIDTH) - page.translate(tx=x_section, ty=y_section) - page.scale(QUARTER_SCALE_FACTOR) - - -def ornate_nup4( - arg_analyze: str, - is_front_page: bool, - new_page: Page, - nup4_geometry: Nup4Geometry, - ) -> None: - 'Apply nup4 line guides onto new_page.' - if arg_analyze: - new_page.draw_borders((0.5, 1.0, 1.0)) - new_page.draw_orth_lines(((True, new_page.box['top']/2), - (False, new_page.box['right']/2)), - line_width=0.1) - printable_offset_x = nup4_geometry.margin - printable_offset_y = nup4_geometry.margin * A4_HEIGHT / A4_WIDTH - new_page.scale(nup4_geometry.shrink_for_margin) - new_page.translate(tx=printable_offset_x, ty=printable_offset_y) - if not (arg_analyze or is_front_page): - return - x_left_spine_limit = A4_WIDTH/2 * nup4_geometry.shrink_for_spine - x_right_spine_limit = A4_WIDTH - x_left_spine_limit - if arg_analyze: - new_page.draw_orth_lines(((False, x_left_spine_limit,), - (False, x_right_spine_limit)), - line_width=0.1, rgb_color=(1.0, 0.5, 1.0)) - if is_front_page: - draw_cut(new_page, x_left_spine_limit, 1) - draw_cut(new_page, x_right_spine_limit, -1) - - -def draw_cut( - page: Page, - x_spine_limit: float, - direction: int - ) -> None: - 'Into canvas draw book binding cut guide at x_spine_limit into direction.' - directed_half_width = 0.5 * CUT_WIDTH * direction - outer_start_x = x_spine_limit - directed_half_width - inner_start_x = x_spine_limit + directed_half_width - middle_point_y = A4_HEIGHT/2 + MIDDLE_POINT_DEPTH * direction - end_point_y = A4_HEIGHT/2 + CUT_DEPTH * direction - page.draw_lines( - ((inner_start_x, A4_HEIGHT/2, x_spine_limit, end_point_y), - (x_spine_limit, end_point_y, x_spine_limit, middle_point_y), - (x_spine_limit, middle_point_y, outer_start_x, A4_HEIGHT/2)), - line_width=0.2) - - def main( ) -> None: 'Full program run to be wrapped into ArgFail catcher.'