Skip to content

Commit

Permalink
Minor docs improvement
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas-C committed Aug 13, 2023
1 parent 1020e53 commit 5451b3b
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 147 deletions.
50 changes: 2 additions & 48 deletions docs/CombineWithPdfrw.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,59 +12,13 @@ with numerous examples and a very clean set of classes modelling the PDF interna
## Adding content onto an existing PDF page

```python
import sys
from fpdf import FPDF
from pdfrw import PageMerge, PdfReader, PdfWriter
from pdfrw.pagemerge import RectXObj

IN_FILEPATH = sys.argv[1]
OUT_FILEPATH = sys.argv[2]
ON_PAGE_INDEX = 1
UNDERNEATH = False # if True, new content will be placed underneath page (painted first)

reader = PdfReader(IN_FILEPATH)
area = RectXObj(reader.pages[0])

def new_content():
fpdf = FPDF(format=(area.w, area.h), unit="pt")
fpdf.add_page()
fpdf.set_font("helvetica", size=36)
fpdf.text(50, 50, "Hello!")
reader = PdfReader(fdata=bytes(fpdf.output()))
return reader.pages[0]

writer = PdfWriter()
writer.pagearray = reader.Root.Pages.Kids
PageMerge(writer.pagearray[ON_PAGE_INDEX]).add(new_content(), prepend=UNDERNEATH).render()
writer.write(OUT_FILEPATH)
{% include "../tutorial/add_on_page_with_pdfrw.py" %}
```

## Adding a page to an existing PDF

```python
import sys
from fpdf import FPDF
from pdfrw import PdfReader, PdfWriter
from pdfrw.pagemerge import RectXObj

IN_FILEPATH = sys.argv[1]
OUT_FILEPATH = sys.argv[2]
NEW_PAGE_INDEX = 1 # set to None to append at the end

reader = PdfReader(IN_FILEPATH)
area = RectXObj(reader.pages[0])

def new_page():
fpdf = FPDF(format=(area.w, area.h), unit="pt")
fpdf.add_page()
fpdf.set_font("helvetica", size=36)
fpdf.text(50, 50, "Hello!")
reader = PdfReader(fdata=bytes(fpdf.output()))
return reader.pages[0]

writer = PdfWriter(trailer=PdfReader(IN_FILEPATH))
writer.addpage(new_page(), at_index=NEW_PAGE_INDEX)
writer.write(OUT_FILEPATH)
{% include "../tutorial/add_new_page_with_pdfrw.py" %}
```

This example relies on [pdfrw _Pull Request_ #216](https://github.com/pmaupin/pdfrw/pull/216).
Expand Down
88 changes: 11 additions & 77 deletions docs/CombineWithPyPDF2.md
Original file line number Diff line number Diff line change
@@ -1,77 +1,11 @@
# Combine with PyPDF2

`fpdf2` cannot **parse** existing PDF files.

However, other Python libraries can be combined with `fpdf2`
in order to add new content to existing PDF files.

This page provides several examples of doing so using [`PyPDF2`](https://github.com/py-pdf/PyPDF2).

## Adding content onto an existing PDF page
In this code snippet, new content will be added on top of existing content:
```python
import io, sys

from fpdf import FPDF
from PyPDF2 import PdfReader, PdfWriter

IN_FILEPATH = sys.argv[1]
OUT_FILEPATH = sys.argv[2]
ON_PAGE_INDEX = 0 # Index of the target page (starts at zero)

def new_content():
pdf = FPDF()
pdf.add_page()
pdf.set_font('times', 'B', 30)
pdf.text(50, 150, 'Hello World!')
return pdf.output()

reader = PdfReader(IN_FILEPATH)
page_overlay = PdfReader(io.BytesIO(new_content())).getPage(0)
reader.getPage(ON_PAGE_INDEX).merge_page(page2=page_overlay)

writer = PdfWriter()
writer.append_pages_from_reader(reader)
writer.write(OUT_FILEPATH)
```

## Adding a page to an existing PDF

```python
import io, sys

from fpdf import FPDF
from PyPDF2 import PdfMerger

IN_FILEPATH = sys.argv[1]
OUT_FILEPATH = sys.argv[2]
ON_PAGE_INDEX = 2 # Index at which the page will be inserted (starts at zero)

def new_page():
pdf = FPDF()
pdf.add_page()
pdf.set_font('times', 'B', 19)
pdf.text(50, 10, 'Hello World!')
return io.BytesIO(pdf.output())

merger = PdfMerger()
merger.merge(position=0, fileobj=IN_FILEPATH)
merger.merge(position=ON_PAGE_INDEX, fileobj=new_page())
merger.write(OUT_FILEPATH)
```

## Altering with PyPDF2 a document generated with fpdf2
A document created with `fpdf2` can the be edited with `PyPDF2`
by passing its `.output()` to a `PyPDF2.PdfReader`:
```python
import io
from fpdf import FPDF
from PyPDF2 import PdfReader

pdf = FPDF()
pdf.add_page()
pdf.set_font('times', 'B', 19)
pdf.text(50, 10, 'Hello World!')

reader = PdfReader(io.BytesIO(pdf.output()))
```
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Redirecting to https://py-pdf.github.io/fpdf2/CombineWithPypdf.html</title>
<meta http-equiv="refresh" content="0; URL=https://py-pdf.github.io/fpdf2/CombineWithPypdf.html">
<link rel="canonical" href="https://py-pdf.github.io/fpdf2/CombineWithPypdf.html">
</head>
<body>
This page moved to https://py-pdf.github.io/fpdf2/CombineWithPypdf.html
</html>
36 changes: 36 additions & 0 deletions docs/CombineWithPypdf.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Combine with pypdf

`fpdf2` cannot **parse** existing PDF files.

However, other Python libraries can be combined with `fpdf2`
in order to add new content to existing PDF files.

This page provides several examples of doing so using [`pypdf`](https://github.com/py-pdf/pypdf), an actively-maintained library formerly known as `PyPDF2`.

## Adding content onto an existing PDF page
In this code snippet, new content will be added on top of existing content:
```python
{% include "../tutorial/add_on_page_with_pypdf.py" %}
```

## Adding a page to an existing PDF

```python
{% include "../tutorial/add_new_page_with_pypdf.py" %}
```

## Altering with pypdf a document generated with fpdf2
A document created with `fpdf2` can the be edited with `pypdf`
by passing its `.output()` to a `pypdf.PdfReader`:
```python
import io
from fpdf import FPDF
from pypdf import PdfReader

pdf = FPDF()
pdf.add_page()
pdf.set_font('times', 'B', 19)
pdf.text(50, 10, 'Hello World!')

reader = PdfReader(io.BytesIO(pdf.output()))
```
7 changes: 3 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,16 +113,15 @@ or [open a discussion](https://github.com/py-pdf/fpdf2/discussions).
### Usage statistics

- [PyPI download stats](https://pypistats.org/packages/fpdf2) - Downloads per release on [Pepy](https://pepy.tech/project/fpdf2)
- [pip trends: fpdf2 VS other PDF rendering libs](https://piptrends.com/compare/fpdf2-vs-fpdf-vs-PyPDF2-vs-borb-vs-reportlab)
- [pip trends: fpdf2 VS other PDF rendering libs](https://piptrends.com/compare/fpdf2-vs-fpdf-vs-pypdf-vs-borb-vs-reportlab)
- packages using `fpdf2` can be listed using [GitHub Dependency graph: Dependents](https://github.com/py-pdf/fpdf2/network/dependents),
[Wheelodex](https://www.wheelodex.org/projects/fpdf2/rdepends/) or [Watchman Pypi](http://www.watchman-pypi.com).
Some are also listed on [its libraries.io page](https://libraries.io/pypi/fpdf2).

### Related ###

* Looking for alternative libraries? Check out [this detailed list of PDF-related Python libs by Patrick Maupin (`pdfrw` author)](https://github.com/pmaupin/pdfrw#other-libraries).
There is also [borb](https://github.com/jorisschellekens/borb), [PyPDF2](https://github.com/py-pdf/PyPDF2), [pikepdf](https://github.com/pikepdf/pikepdf), [WeasyPrint](https://github.com/Kozea/WeasyPrint), [pydyf](https://pypi.org/project/pydyf/) and [PyMuPDF](https://pymupdf.readthedocs.io/en/latest/index.html): [features comparison](https://pymupdf.readthedocs.io/en/latest/about.html), [examples](https://github.com/pymupdf/PyMuPDF-Utilities/tree/master/examples#examples), [Jupyter notebooks](https://github.com/pymupdf/PyMuPDF-Utilities/tree/master/jupyter-notebooks).
We have some documentations about combining `fpdf2` with [`borb`](CombineWithBorb.md), [`pdfrw`](CombineWithPdfrw.md), & [`PyPDF2`](CombineWithPyPDF2.md).
* Looking for alternative libraries? Check out [pypdf](https://github.com/py-pdf/pypdf), [borb](https://github.com/jorisschellekens/borb), [pikepdf](https://github.com/pikepdf/pikepdf), [WeasyPrint](https://github.com/Kozea/WeasyPrint), [pydyf](https://pypi.org/project/pydyf/) and [PyMuPDF](https://pymupdf.readthedocs.io/en/latest/index.html): [features comparison](https://pymupdf.readthedocs.io/en/latest/about.html), [examples](https://github.com/pymupdf/PyMuPDF-Utilities/tree/master/examples#examples), [Jupyter notebooks](https://github.com/pymupdf/PyMuPDF-Utilities/tree/master/jupyter-notebooks).
We have some documentations about combining `fpdf2` with [`borb`](CombineWithBorb.md) & [`pypdf`](CombineWithPypdf.md).
* [Create PDFs with Python](https://www.youtube.com/playlist?list=PLjNQtX45f0dR9K2sMJ5ad9wVjqslNBIC0) : a series of tutorial videos by bvalgard
* [digidigital/Extensions-and-Scripts-for-pyFPDF-fpdf2](https://github.com/digidigital/Extensions-and-Scripts-for-pyFPDF-fpdf2) : scripts ported from PHP to add transpareny to elements of the page or part of an image, allow to write circular text,
draw pie charts and bar diagrams, embed JavaScript, draw rectangles with rounded corners, draw a star shape,
Expand Down
2 changes: 1 addition & 1 deletion mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ nav:
- 'File attachments': 'FileAttachments.md'
- 'Mixing other libs':
- 'Combine with borb': 'CombineWithBorb.md'
- 'Combine with pypdf': 'CombineWithPypdf.md'
- 'Combine with pdfrw': 'CombineWithPdfrw.md'
- 'Combine with PyPDF2': 'CombineWithPyPDF2.md'
- 'Matplotlib, Pandas, Plotly, Pygal': 'CombineWithChartingLibs.md'
- 'Templating with Jinja': 'TemplatingWithJinja.md'
- 'Usage in web APIs': 'UsageInWebAPI.md'
Expand Down
7 changes: 0 additions & 7 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import os
import pathlib
import shutil
import sys
import tracemalloc
import warnings

Expand Down Expand Up @@ -210,12 +209,6 @@ def subst_streams_with_hashes(in_lines):


def _qpdf(input_pdf_filepath):
if sys.platform == "cygwin":
# Lucas (2021/01/06) : this conversion of UNIX file paths to Windows ones is only needed
# for my development environment: Cygwin, a UNIX system, with a qpdf Windows binary. Sorry for the kludge!
input_pdf_filepath = (
_run_cmd("cygpath", "-w", str(input_pdf_filepath)).decode().strip()
)
return _run_cmd(
"qpdf",
"--deterministic-id",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
#!/usr/bin/env python3

# USAGE: ./add_new_page.py $in_filepath $out_filepath

import sys

from fpdf import FPDF
Expand Down
23 changes: 23 additions & 0 deletions tutorial/add_new_page_with_pypdf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env python3
import io, sys

from fpdf import FPDF
from PyPDF2 import PdfMerger

IN_FILEPATH = sys.argv[1]
OUT_FILEPATH = sys.argv[2]
ON_PAGE_INDEX = 2 # Index at which the page will be inserted (starts at zero)


def new_page():
pdf = FPDF()
pdf.add_page()
pdf.set_font("times", "B", 19)
pdf.text(50, 10, "Hello World!")
return io.BytesIO(pdf.output())


merger = PdfMerger()
merger.merge(position=0, fileobj=IN_FILEPATH)
merger.merge(position=ON_PAGE_INDEX, fileobj=new_page())
merger.write(OUT_FILEPATH)
15 changes: 8 additions & 7 deletions tutorial/add_on_page.py → tutorial/add_on_page_with_pdfrw.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
#!/usr/bin/env python3

# USAGE: ./add_on_page.py $in_filepath $out_filepath
# Inspired by https://github.com/pmaupin/pdfrw/blob/master/examples/watermark.py

import sys

from fpdf import FPDF
from pdfrw import PageMerge, PdfReader, PdfWriter
from pdfrw.pagemerge import RectXObj

IN_FILEPATH = sys.argv[1]
OUT_FILEPATH = sys.argv[2]
Expand All @@ -15,17 +11,22 @@
False # if True, new content will be placed underneath page (painted first)
)

reader = PdfReader(IN_FILEPATH)
area = RectXObj(reader.pages[0])


def new_content():
fpdf = FPDF()
fpdf = FPDF(format=(area.w, area.h), unit="pt")
fpdf.add_page()
fpdf.set_font("helvetica", size=36)
fpdf.text(50, 50, "Hello!")
reader = PdfReader(fdata=bytes(fpdf.output()))
return reader.pages[0]


writer = PdfWriter(trailer=PdfReader(IN_FILEPATH))
writer = PdfWriter()
writer.pagearray = reader.Root.Pages.Kids
writer.pagearray = writer.pagearray[0].Kids
PageMerge(writer.pagearray[ON_PAGE_INDEX]).add(
new_content(), prepend=UNDERNEATH
).render()
Expand Down
26 changes: 26 additions & 0 deletions tutorial/add_on_page_with_pypdf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env python3
import io, sys

from fpdf import FPDF
from pypdf import PdfReader, PdfWriter

IN_FILEPATH = sys.argv[1]
OUT_FILEPATH = sys.argv[2]
ON_PAGE_INDEX = 0 # Index of the target page (starts at zero)


def new_content():
pdf = FPDF()
pdf.add_page()
pdf.set_font("times", "B", 30)
pdf.text(50, 150, "Hello World!")
return pdf.output()


reader = PdfReader(IN_FILEPATH)
page_overlay = PdfReader(io.BytesIO(new_content())).pages[0]
reader.pages[ON_PAGE_INDEX].merge_page(page2=page_overlay)

writer = PdfWriter()
writer.append_pages_from_reader(reader)
writer.write(OUT_FILEPATH)

0 comments on commit 5451b3b

Please sign in to comment.