Recent posts

#41
PDF Generation / Re: [Q] Python script written ...
Last post by jirib - May 11, 2025, 10:57:27 AM
Quote from: Nermander on May 11, 2025, 10:39:52 AMDo I understand it right, this script takes a PDF and make a cover of the first and last page?

So, with a 12 page PDF, pages 1 and 12 end up in a cover PDF (landscape, 2-up, with a spine between the pages) and the pages 2-11 end up in a "content only" PDF?

And the width of the spine is calculated based on the number of pages and an assumed page thickness of 0.083?

But what about the insides of the cover? Those will be blank?

Not really:

...
cover_pairs = [
    (reader.pages[total_pages - 1], reader.pages[0]),
    (reader.pages[1], reader.pages[total_pages - 2])
]
...
# === Generate 2-page cover PDF
cover_writer = PdfWriter()
 
for i, (left, right) in enumerate(cover_pairs):
    merged = PageObject.create_blank_page(None, TOTAL_WIDTH, TOTAL_HEIGHT)
 
    if i == 0:
        packet = BytesIO()
        c = canvas.Canvas(packet, pagesize=(TOTAL_WIDTH, TOTAL_HEIGHT))
        draw_marks(c, TOTAL_WIDTH, TOTAL_HEIGHT, spine_width)
        c.showPage()
        c.save()
        packet.seek(0)
        marks = PdfReader(packet).pages[0]
        merged.merge_page(marks)
 
    merged.merge_translated_page(left, tx=BLEED, ty=BLEED)
    merged.merge_translated_page(right, tx=BLEED + A5_WIDTH + spine_width, ty=BLEED)
    cover_writer.add_page(merged)

with open(cover_out, "wb") as f:
    cover_writer.write(f)
...

So, it generates cover with 'cover_pairs'..., however, logically, it places crop marks and spine marks only on the first/outside cover page.
#42
PDF Generation / Re: [Q] Python script written ...
Last post by Nermander - May 11, 2025, 10:39:52 AM
Do I understand it right, this script takes a PDF and make a cover of the first and last page?

So, with a 12 page PDF, pages 1 and 12 end up in a cover PDF (landscape, 2-up, with a spine between the pages) and the pages 2-11 end up in a "content only" PDF?

And the width of the spine is calculated based on the number of pages and an assumed page thickness of 0.083?

But what about the insides of the cover? Those will be blank?
#43
PDF Generation / Re: [Q] Python script written ...
Last post by jirib - May 11, 2025, 09:52:30 AM
I even did not know how crop marks or spine marks should look like :/ I could not find an exact description. Maybe in the scribus source (for crop marks) ???
#44
PDF Generation / Re: [Q] Python script written ...
Last post by a.l.e - May 10, 2025, 02:56:25 PM
I can't say much about the calculation, sorry.

But if the calculations are validate by people who know more about spine marks than me, it might also be interesting to have a version that runs inside of Scribus and adds the marks on a dedicated layer.
#45
PDF Generation / [Q] Python script written to g...
Last post by jirib - May 10, 2025, 10:50:36 AM
Hi,
what do you think about this python script to create cover page from a PDF with spine marks ?

---%>---
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm, inch
from reportlab.lib.colors import black
from pypdf import PdfReader, PdfWriter, PageObject
from io import BytesIO
from pathlib import Path
import sys

pt = inch / 72.0
CROP_OFFSET = 6 * pt
CROP_LINE_WIDTH = 0.2 * pt
CROP_LEN = 5 * mm
A5_WIDTH = 148.5 * mm
HEIGHT = 210 * mm
BLEED = 5 * mm

def draw_marks(c, total_width, total_height, spine_width):
    c.setStrokeColor(black)
    c.setLineWidth(CROP_LINE_WIDTH)

    xL = BLEED
    xR = total_width - BLEED
    xCL = xL - CROP_OFFSET
    xCR = xR + CROP_OFFSET
    yB = BLEED
    yT = total_height - BLEED
    yCB = yB - CROP_OFFSET
    yCT = yT + CROP_OFFSET

    c.line(xL, yCT, xL, yCT + CROP_LEN)
    c.line(xR, yCT, xR, yCT + CROP_LEN)
    c.line(xCL - CROP_LEN, yT, xCL, yT)
    c.line(xCR, yT, xCR + CROP_LEN, yT)
    c.line(xL, yCB, xL, yCB - CROP_LEN)
    c.line(xR, yCB, xR, yCB - CROP_LEN)
    c.line(xCL - CROP_LEN, yB, xCL, yB)
    c.line(xCR, yB, xCR + CROP_LEN, yB)

    xS1 = BLEED + A5_WIDTH
    xS2 = xS1 + spine_width
    for x in [xS1, xS2]:
        c.line(x, yCB, x, yCB - CROP_LEN)
        c.line(x, yCT, x, yCT + CROP_LEN)

if len(sys.argv) < 2:
    print("Usage: python generate_cover.py input.pdf")
    sys.exit(1)

input_path = Path(sys.argv[1])
reader = PdfReader(str(input_path))
total_pages = len(reader.pages)
if total_pages < 4:
    raise ValueError("❌ PDF must have at least 4 pages.")

cover_pairs = [
    (reader.pages[total_pages - 1], reader.pages[0]),
    (reader.pages[1], reader.pages[total_pages - 2])
]
cover_indices = {0, 1, total_pages - 2, total_pages - 1}

content_page_count = total_pages - 4
spine_width = round(content_page_count * 0.083, 3) * mm
TOTAL_WIDTH = 2 * A5_WIDTH + spine_width + 2 * BLEED
TOTAL_HEIGHT = HEIGHT + 2 * BLEED

# ✅ Output paths
base = input_path.with_suffix('')
cover_out = base.with_name(base.name + "_cover_final.pdf")
content_out = base.with_name(base.name + "_content.pdf")

# === Generate 2-page cover PDF
cover_writer = PdfWriter()

for i, (left, right) in enumerate(cover_pairs):
    merged = PageObject.create_blank_page(None, TOTAL_WIDTH, TOTAL_HEIGHT)

    if i == 0:
        packet = BytesIO()
        c = canvas.Canvas(packet, pagesize=(TOTAL_WIDTH, TOTAL_HEIGHT))
        draw_marks(c, TOTAL_WIDTH, TOTAL_HEIGHT, spine_width)
        c.showPage()
        c.save()
        packet.seek(0)
        marks = PdfReader(packet).pages[0]
        merged.merge_page(marks)

    merged.merge_translated_page(left, tx=BLEED, ty=BLEED)
    merged.merge_translated_page(right, tx=BLEED + A5_WIDTH + spine_width, ty=BLEED)
    cover_writer.add_page(merged)

with open(cover_out, "wb") as f:
    cover_writer.write(f)

# === Generate content-only PDF
content_writer = PdfWriter()
for i in range(total_pages):
    if i not in cover_indices:
        content_writer.add_page(reader.pages[i])

with open(content_out, "wb") as f:
    content_writer.write(f)

# === Summary
print("✅ Cover PDF:   ", cover_out.name)
print("✅ Content PDF: ", content_out.name)
print("📏 Spine width: ", round(spine_width / mm, 3), "mm")
---%<---

#46
Scripts and Plugins / Re: Replacing selected text
Last post by prcek - May 10, 2025, 09:55:37 AM
Well, definitely I was checking that repo as well :-)
But if you don't know what exactly you're looking for it is more difficult to find it.
And as I wrote, the problem with find() can arise in case of a repetitive text parts.
Thank you again, getSelectedTextRange() seems to do what I need.
#47
Features / Re: Feature: Paste formatting
Last post by a.l.e - May 10, 2025, 09:28:53 AM
The plan is (probably) to have a creation of styles based on the current selection and then allow to apply the style with the keyboard.

We're not that far from it : - )

Once we have that, it should be easy to also add a copy paste for text formatting, but -- personally -- i'd prefer not to have the feature (most people will not find it, and those who find it are not encouraged to go for a better workflow)
#48
Scripts and Plugins / Re: Replacing selected text
Last post by a.l.e - May 10, 2025, 08:18:30 AM
Now that you say it, I have the feeling that I already have used it...

I did a quick check and found this:


https://github.com/aoloe/scribus-script-repository/blob/master/sort_lines/sort_lines.py

It does not seem to do what it should, but it does get the text selection and it even provides a polyfill : - )
#49
Scripts and Plugins / Re: Replacing selected text
Last post by prcek - May 10, 2025, 06:44:32 AM
Thank you very much!
It was really weird to me nobody needed it before. And I didn't find it in any script I checked

I was looking for it in output of
import scribus
help(scribus)

I run it on 1.6.1 (appimage) and it is missing there (checked right now). Could it be the reason it is missing in your generated doc?

It is present in 1.6.3 and 1.6.4. help, though.
#50
Features / Feature: Paste formatting
Last post by transnomadic - May 09, 2025, 08:11:11 PM
I would like the ability to apply the formatting or character style to any hi-lighted text or object from the last text or object that I've copied to my clipboard. The formatting or style would be applied either through a special shortcut (CTRL + SHIFT + V) or through an Edit > Paste format menu item.