From 31f4e56e535783311b553b9f8b0409125f61f98e Mon Sep 17 00:00:00 2001
From: "allcontributors[bot]"
<46447321+allcontributors[bot]@users.noreply.github.com>
Date: Wed, 21 Dec 2022 09:08:09 +0100
Subject: [PATCH 1/7] add Bubbu0129 as a contributor for bug (#633)
Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
---
.all-contributorsrc | 3 ++-
README.md | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/.all-contributorsrc b/.all-contributorsrc
index f009e5635..c25fdefea 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -742,7 +742,8 @@
"avatar_url": "https://avatars.githubusercontent.com/u/93034081?v=4",
"profile": "https://github.com/Bubbu0129",
"contributions": [
- "code"
+ "code",
+ "bug"
]
}
],
diff --git a/README.md b/README.md
index 653c7fb52..e4f9d68a4 100644
--- a/README.md
+++ b/README.md
@@ -219,7 +219,7 @@ This library could only exist thanks to the dedication of many volunteers around
Sean 💻 |
Anderson Herzogenrath da Costa 💬 💻 |
Yi Wei Lan ⚠️ |
- CpDong 💻 |
+ CpDong 💻 🐛 |
From e02fc576014b827d9f31a5fc76fb224779efc582 Mon Sep 17 00:00:00 2001
From: Lucas Cimon <925560+Lucas-C@users.noreply.github.com>
Date: Wed, 21 Dec 2022 19:30:44 +0100
Subject: [PATCH 2/7] Improving add_link() (#615)
---
CHANGELOG.md | 7 +-
docs/CombineWithPdfrw.md | 13 +++-
docs/Links.md | 3 +-
docs/Logging.md | 64 +++++++++++++++---
docs/Tutorial-de.md | 3 +-
docs/Tutorial-es.md | 4 +-
docs/Tutorial-fr.md | 2 +-
docs/Tutorial-gr.md | 4 +-
docs/Tutorial-he.md | 2 +-
docs/Tutorial-it.md | 4 +-
docs/Tutorial-pt.md | 2 +-
docs/Tutorial-ru.md | 2 +-
...77\340\244\202\340\244\246\340\245\200.md" | 2 -
docs/Tutorial.md | 4 +-
fpdf/__init__.py | 3 +-
fpdf/fpdf.py | 46 +++++++++++--
fpdf/html.py | 3 +-
fpdf/output.py | 17 ++++-
fpdf/syntax.py | 8 +++
test/image/image_x_align_center.pdf | Bin 0 -> 28191 bytes
test/image/image_x_align_right.pdf | Bin 0 -> 28190 bytes
test/image/test_image_align.py | 24 +++++++
test/image/test_oversized.py | 2 +-
test/inserting_same_page_link_twice.pdf | Bin 0 -> 1267 bytes
test/outline/test_outline.py | 3 +-
test/test_links.py | 38 +++++++++++
tutorial/tuto6.py | 3 +-
tutorial/unicode.py | 0
28 files changed, 208 insertions(+), 55 deletions(-)
create mode 100644 test/image/image_x_align_center.pdf
create mode 100644 test/image/image_x_align_right.pdf
create mode 100644 test/image/test_image_align.py
create mode 100644 test/inserting_same_page_link_twice.pdf
mode change 100644 => 100755 tutorial/unicode.py
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d94dfc9b9..191a03900 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,10 +18,13 @@ This can also be enabled programmatically with `warnings.simplefilter('default',
## [2.6.1] - not released yet
### Added
+* the `x` parameter of [`FPDF.image()`](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image) can now accepts a value of `"C"` / `Align.C` / `"R"` / `Align.R` to horizontally position the image centered or aligned right
* support for `[]()` links when `markdown=True`
-* support for `line-height` attribute of paragraph (``) in `write_html()`
+* support for `line-height` attribute of paragraph (`
`) in `write_html()` - thanks to @Bubbu0129
### Changed
-* `write_html()`now generates warnings for unclosed HTML tags, unless `warn_on_tags_not_matching=False` is set
+* `add_link()` creates a link to the current page by default, and now accepts optional parameters: `x`, `y`, `page` & `zoom`.
+ Hence calling `set_link()` is not needed anymore after creating a link with `add_link()`.
+* `write_html()` now generates warnings for unclosed HTML tags, unless `warn_on_tags_not_matching=False` is set
## [2.6.0] - 2022-11-20
### Added
diff --git a/docs/CombineWithPdfrw.md b/docs/CombineWithPdfrw.md
index b3458d6d9..ac65645b8 100644
--- a/docs/CombineWithPdfrw.md
+++ b/docs/CombineWithPdfrw.md
@@ -15,21 +15,24 @@ with numerous examples and a very clean set of classes modelling the PDF interna
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()
+ fpdf = FPDF(format=(area.w, area.h))
fpdf.add_page()
fpdf.set_font("helvetica", size=36)
fpdf.text(50, 50, "Hello!")
reader = PdfReader(fdata=bytes(fpdf.output()))
return reader.pages[0]
-reader = PdfReader(IN_FILEPATH)
writer = PdfWriter()
writer.pagearray = reader.Root.Pages.Kids
PageMerge(writer.pagearray[ON_PAGE_INDEX]).add(new_content(), prepend=UNDERNEATH).render()
@@ -42,13 +45,17 @@ writer.write(OUT_FILEPATH)
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()
+ fpdf = FPDF(format=(area.w, area.h))
fpdf.add_page()
fpdf.set_font("helvetica", size=36)
fpdf.text(50, 50, "Hello!")
diff --git a/docs/Links.md b/docs/Links.md
index 73591abac..cb2b4dcf4 100644
--- a/docs/Links.md
+++ b/docs/Links.md
@@ -70,8 +70,7 @@ pdf.add_page()
# Displaying a full-width cell with centered text:
pdf.cell(w=pdf.epw, txt="Welcome on first page!", align="C")
pdf.add_page()
-link = pdf.add_link()
-pdf.set_link(link, page=1)
+link = pdf.add_link(page=1)
pdf.cell(txt="Internal link to first page", border=1, link=link)
pdf.output("internal_link.pdf")
```
diff --git a/docs/Logging.md b/docs/Logging.md
index cf54f18b7..4c5b17fff 100644
--- a/docs/Logging.md
+++ b/docs/Logging.md
@@ -9,19 +9,61 @@ Here is an example of setup code to display them:
```python
import logging
-logging.basicConfig(format="%(asctime)s %(filename)s [%(levelname)s] %(message)s",
+logging.basicConfig(format="%(asctime)s %(name)s [%(levelname)s] %(message)s",
datefmt="%H:%M:%S", level=logging.DEBUG)
```
Example output using the [Tutorial](Tutorial.md) first code snippet:
- 14:09:56 fpdf.py [DEBUG] Final doc sections size summary:
- 14:09:56 fpdf.py [DEBUG] - header.size: 9.0B
- 14:09:56 fpdf.py [DEBUG] - pages.size: 306.0B
- 14:09:56 fpdf.py [DEBUG] - resources.fonts.size: 101.0B
- 14:09:56 fpdf.py [DEBUG] - resources.images.size: 0.0B
- 14:09:56 fpdf.py [DEBUG] - resources.dict.size: 104.0B
- 14:09:56 fpdf.py [DEBUG] - info.size: 54.0B
- 14:09:56 fpdf.py [DEBUG] - catalog.size: 103.0B
- 14:09:56 fpdf.py [DEBUG] - xref.size: 169.0B
- 14:09:56 fpdf.py [DEBUG] - trailer.size: 60.0B
+ 19:25:24 fpdf.output [DEBUG] Final size summary of the biggest document sections:
+ 19:25:24 fpdf.output [DEBUG] - pages: 223.0B
+ 19:25:24 fpdf.output [DEBUG] - fonts: 102.0B
+
+## fonttools verbose logs
+
+Since `fpdf2` v2.5.7, verbose **INFO** logs are generated by `fonttools`,
+a library we use to parse font files:
+
+```
+fontTools.subset [INFO] maxp pruned
+fontTools.subset [INFO] cmap pruned
+fontTools.subset [INFO] post pruned
+fontTools.subset [INFO] EBDT dropped
+fontTools.subset [INFO] EBLC dropped
+fontTools.subset [INFO] GDEF dropped
+fontTools.subset [INFO] GPOS dropped
+fontTools.subset [INFO] GSUB dropped
+fontTools.subset [INFO] DSIG dropped
+fontTools.subset [INFO] name pruned
+fontTools.subset [INFO] glyf pruned
+fontTools.subset [INFO] Added gid0 to subset
+fontTools.subset [INFO] Added first four glyphs to subset
+fontTools.subset [INFO] Closing glyph list over 'glyf': 25 glyphs before
+fontTools.subset [INFO] Glyph names: ['.notdef', 'b', 'braceleft', 'braceright', 'd', 'e', 'eight', 'five', 'four', 'glyph1', 'glyph2', 'h', 'l', 'n', 'nine', 'o', 'one', 'r', 'seven', 'six', 'space', 'three', 'two', 'w', 'zero']
+fontTools.subset [INFO] Glyph IDs: [0, 1, 2, 3, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 69, 71, 72, 75, 79, 81, 82, 85, 90, 94, 96]
+fontTools.subset [INFO] Closed glyph list over 'glyf': 25 glyphs after
+fontTools.subset [INFO] Glyph names: ['.notdef', 'b', 'braceleft', 'braceright', 'd', 'e', 'eight', 'five', 'four', 'glyph1', 'glyph2', 'h', 'l', 'n', 'nine', 'o', 'one', 'r', 'seven', 'six', 'space', 'three', 'two', 'w', 'zero']
+fontTools.subset [INFO] Glyph IDs: [0, 1, 2, 3, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 69, 71, 72, 75, 79, 81, 82, 85, 90, 94, 96]
+fontTools.subset [INFO] Retaining 25 glyphs
+fontTools.subset [INFO] head subsetting not needed
+fontTools.subset [INFO] hhea subsetting not needed
+fontTools.subset [INFO] maxp subsetting not needed
+fontTools.subset [INFO] OS/2 subsetting not needed
+fontTools.subset [INFO] hmtx subsetted
+fontTools.subset [INFO] cmap subsetted
+fontTools.subset [INFO] fpgm subsetting not needed
+fontTools.subset [INFO] prep subsetting not needed
+fontTools.subset [INFO] cvt subsetting not needed
+fontTools.subset [INFO] loca subsetting not needed
+fontTools.subset [INFO] post subsetted
+fontTools.subset [INFO] name subsetting not needed
+fontTools.subset [INFO] glyf subsetted
+fontTools.subset [INFO] head pruned
+fontTools.subset [INFO] OS/2 Unicode ranges pruned: [0]
+fontTools.subset [INFO] glyf pruned
+```
+
+You can easily suppress those logs with this single line of code:
+```
+logging.getLogger('fontTools.subset').level = logging.WARN
+```
diff --git a/docs/Tutorial-de.md b/docs/Tutorial-de.md
index 1a7e92a86..56d4d3c32 100644
--- a/docs/Tutorial-de.md
+++ b/docs/Tutorial-de.md
@@ -199,8 +199,7 @@ Der Anfang des Satzes wird in "normalem" Stil geschrieben, dann mit der Methode
Um einen internen Link hinzuzufügen, der auf die zweite Seite verweist, nutzen wir die Methode
[`add_link()`](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), die einen anklickbaren Bereich erzeugt,
- den wir "link" nennen und der auf eine andere Stelle innerhalb des Dokuments verweist. Auf der zweiten Seite verwenden wir
- [`set_link()`](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link), um den Zielbereich für den soeben erstellten Link zu definieren.
+ den wir "link" nennen und der auf eine andere Stelle innerhalb des Dokuments verweist.
Um einen externen Link mit Hilfe eines Bildes zu erstellen, verwenden wir [`image()`](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image). Es besteht die Möglichkeit, der Methode ein Linkziel als eines ihrer Argumente zu übergeben. Der Link kann sowohl einer interner als auch ein externer sein.
diff --git a/docs/Tutorial-es.md b/docs/Tutorial-es.md
index e78cce8d6..7a17f1efc 100644
--- a/docs/Tutorial-es.md
+++ b/docs/Tutorial-es.md
@@ -243,9 +243,7 @@ En la primera página del ejemplo usamos
Para agregar un enlace interno apuntando a la segunda página, usamos el método
[add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link)
, el cual crea un área clicable a la que nombramos "link" que redirige a
- otro lugar dentro del documento. En la segunda página usamos
- [set_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link)
- para definir el área de destino para el enlace que acabamos de crear.
+ otro lugar dentro del documento.
Para crear un enlace externo usando una imagen, usamos
[image()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image)
diff --git a/docs/Tutorial-fr.md b/docs/Tutorial-fr.md
index 9450ef58b..c6687a679 100644
--- a/docs/Tutorial-fr.md
+++ b/docs/Tutorial-fr.md
@@ -151,7 +151,7 @@ En revanche, son principal inconvénient est que nous ne pouvons pas justifier l
Dans la première page de l'exemple, nous avons utilisé [write()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write) à cette fin. Le début de la phrase est écrit en style normal, puis en utilisant la méthode [set_font()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_font), nous sommes passés au soulignement et avons terminé la phrase.
-Pour ajouter un lien interne pointant vers la deuxième page, nous avons utilisé la méthode [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), qui crée une zone cliquable que nous avons nommée `link` et qui dirige vers un autre endroit du document. Sur la deuxième page, nous avons utilisé [set_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link) pour définir la zone de destination du lien que nous venons de créer.
+Pour ajouter un lien interne pointant vers la deuxième page, nous avons utilisé la méthode [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), qui crée une zone cliquable que nous avons nommée `link` et qui dirige vers une autre page du document.
Pour créer le lien externe à l'aide d'une image, nous avons utilisé [image()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image). Cette méthode a la possibilité de transmettre un lien comme l'un de ses arguments. Le lien peut être interne ou externe.
diff --git a/docs/Tutorial-gr.md b/docs/Tutorial-gr.md
index c6a63b202..c80460a09 100644
--- a/docs/Tutorial-gr.md
+++ b/docs/Tutorial-gr.md
@@ -155,9 +155,7 @@ pdf.cell(60, 10, 'Powered by FPDF.', new_x="LMARGIN", new_y="NEXT", align='C')
Στην πρώτη σελίδα του παραδείγματος χρησιμοποιήσαμε την μέθοδο [write()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write) για αυτό το σκοπό. Το πρώτο κομμάτι της πρότασης είναι γραμμένο ως απλό κείμενο, ενώ στη συνέχεια, αφού χρησιμοποιήσαμε την μέθοδο [set_font()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_font), αλλάξαμε το στυλ κειμένου σε υπογράμμιση και κλείσαμε την πρόταση.
Για να προσθέσουμε έναν εσωτερικό σύνδεσμο ο οποίος θα κατευθύνει στην επόμενη σελίδα, χρησιμοποιήσαμε την μέθοδο
- [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), η οποία δημιουργεί μία επιφανεία με όνομα "link". Αν κλικάρουμε την επιφάνεια αυτή μεταφερόμαστε σε μία άλλη τοποθεσία του αρχείου. Στην δεύτερη σελίδα χρησιμοποιήσαμε την μέθοδο
- [set_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link)
- για να ορίσουμε τον προορισμό του συνδέσμου που μόλις δημιουργήσαμε.
+ [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), η οποία δημιουργεί μία επιφανεία με όνομα "link". Αν κλικάρουμε την επιφάνεια αυτή μεταφερόμαστε σε μία άλλη τοποθεσία του αρχείου.
Για να δημιουργήσουμε έναν εξωτερικό σύνδεσμο μέσω μιας εικόνας, θα χρησιμοποιήσουμε την μέθοδο [image()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image). Αυτή η μέθοδος μας δίνει την επιλογή να περάσουμε έναν σύνδεσμο ως τιμή σε μία από τις παραμέτρους της. Ο σύνδεσμος μπορεί να είναι εσωτερικός ή εξωτερικός.
diff --git a/docs/Tutorial-he.md b/docs/Tutorial-he.md
index dc5ed2ff4..59d6e7308 100644
--- a/docs/Tutorial-he.md
+++ b/docs/Tutorial-he.md
@@ -153,7 +153,7 @@ pdf.cell(60, 10, 'Powered by FPDF.', new_x="LMARGIN", new_y="NEXT", align='C')
בעמוד הראשון של הדוגמא השתמשנו [()write](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write) למטרה זו. תחילת המשפט נכתב בסגנון טקסט רגיל ואז על ידי שימוש במתודה [()set_font](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_font) החלפנו לטקסט עם קו תחתון לסיום המשפט.
-כדי להוסיף קישור פנימי שמוביל לעמוד השני השתמשנו במתודה [()add_link](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link) שוצרת איזור ניתן להקלקה שנתנו לו את השם "קישור" שמוביל לאיזור אחר באותו המסמך. בעמוד השני השתמשנו ב[()set_link](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link) על מנת להגדיר את האיזור אליו הקישור שיצרנו מוביל.
+כדי להוסיף קישור פנימי שמוביל לעמוד השני השתמשנו במתודה [()add_link](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link) שוצרת איזור ניתן להקלקה שנתנו לו את השם "קישור" שמוביל לאיזור אחר באותו המסמך.
על מנת ליצור קישור חיצני באמצעות תמונה, השתמשנו במתודה [()image](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image). למתודה יש אופציה לקבל קישור כאחד הפרמטרים שלה. הקישור יכול להיות פנימי או חיצוני.
diff --git a/docs/Tutorial-it.md b/docs/Tutorial-it.md
index 592213753..f19d0f6f9 100644
--- a/docs/Tutorial-it.md
+++ b/docs/Tutorial-it.md
@@ -183,9 +183,7 @@ Nella prima pagina dell'esempio, abbiamo usato
Per aggiungere un link interno che puntasse alla seconda pagina, abbiamo utilizzato
[add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link)
-che crea un area cliccabile che abbiamo chiamato "link" che redirige ad un altro punto del documento. Nella seconda pagina abbiamo usato
- [set_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link)
- per definire un'area di destinazione per il link creato in precedenza.
+che crea un area cliccabile che abbiamo chiamato "link" che redirige ad un altro punto del documento.
Per creare un link esterno utilizzando un'immagine, abbiamo usato
[image()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image)
diff --git a/docs/Tutorial-pt.md b/docs/Tutorial-pt.md
index 7df457f46..6064beb42 100644
--- a/docs/Tutorial-pt.md
+++ b/docs/Tutorial-pt.md
@@ -174,7 +174,7 @@ Por outro lado, a sua principal desvantagem é que não podemos justificar o tex
Na primeira página do exemplo, usámos [write()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write)
para este propósito. O início da frase está escrita no estilo de texto normal, depois usando o método [set_font()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_font), trocamos para sublinhado e acabámos a frase.
-Para adicionar o link externo a apontar para a segunda página, nós usámos o método [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), que cria uma área clicável à qual demos o nome de “link” que direciona para outra parte do documento. Na segunda página, usámos [set_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link) para definir uma área de destino para o link que acabámos de criar.
+Para adicionar o link externo a apontar para a segunda página, nós usámos o método [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), que cria uma área clicável à qual demos o nome de “link” que direciona para outra parte do documento.
Para criar o link externo usando uma imagem, usámos [image()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image). O método tem a opção de passar um link como um dos seus argumentos. O link pode ser interno ou externo.
diff --git a/docs/Tutorial-ru.md b/docs/Tutorial-ru.md
index db0bfc0f0..1712f0f6c 100644
--- a/docs/Tutorial-ru.md
+++ b/docs/Tutorial-ru.md
@@ -146,7 +146,7 @@ pdf.cell(60, 10, 'Powered by FPDF.', new_x="LMARGIN", new_y="NEXT", align='C')
На первой странице примера мы использовали для этой цели [write()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.write). Начало предложения написано текстом обычного стиля, затем, используя метод [set_font()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_font), мы переключились на подчеркивание и закончили предложение.
-Для добавления внутренней ссылки, указывающей на вторую страницу, мы использовали метод [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), который создает кликабельную область, названную нами "link", которая ведет в другое место внутри документа. На второй странице мы использовали метод [set_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link), чтобы определить целевую зону для только что созданной ссылки.
+Для добавления внутренней ссылки, указывающей на вторую страницу, мы использовали метод [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link), который создает кликабельную область, названную нами "link", которая ведет в другое место внутри документа.
Чтобы создать внешнюю ссылку с помощью изображения, мы использовали метод [image()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image). Этот метод имеет возможность передать ссылку в качестве одного из аргументов. Ссылка может быть как внутренней, так и внешней.
diff --git "a/docs/Tutorial-\340\244\271\340\244\277\340\244\202\340\244\246\340\245\200.md" "b/docs/Tutorial-\340\244\271\340\244\277\340\244\202\340\244\246\340\245\200.md"
index d3fd5b425..f64e976bd 100644
--- "a/docs/Tutorial-\340\244\271\340\244\277\340\244\202\340\244\246\340\245\200.md"
+++ "b/docs/Tutorial-\340\244\271\340\244\277\340\244\202\340\244\246\340\245\200.md"
@@ -203,8 +203,6 @@ Logo को निर्दिष्ट करके [image](fpdf/fpdf.html#fpdf
दूसरे पृष्ठ की ओर इशारा करते हुए एक आंतरिक लिंक जोड़ने के लिए, हमने [add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link) विधि का उपयोग किया, जो एक क्लिक करने योग्य क्षेत्र बनाता है जिसे हमने "Link" नाम दिया है जो दस्तावेज़ के भीतर किसी अन्य स्थान पर निर्देशित करता है।
-दूसरे पृष्ठ पर, हमने अभी-अभी बनाए गए लिंक के लिए गंतव्य क्षेत्र को परिभाषित करने के लिए [set_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link) का उपयोग किया।
-
Image का उपयोग करके बाहरी लिंक बनाने के लिए, हमने [image()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image) का उपयोग किया। विधि में एक लिंक को इसके तर्कों में से एक के रूप में पारित करने का विकल्प होता है। लिंक आंतरिक या बाहरी दोनों हो सकता है।
एक विकल्प के रूप में, फ़ॉन्ट शैली बदलने और लिंक जोड़ने का दूसरा विकल्प `write_html()` पद्धति का उपयोग करना है। यह एक HTML पार्सर है, जो टेक्स्ट जोड़ने, फ़ॉन्ट शैली बदलने और html का उपयोग करके लिंक जोड़ने की अनुमति देता है।
diff --git a/docs/Tutorial.md b/docs/Tutorial.md
index 56a2be2d0..8142de057 100644
--- a/docs/Tutorial.md
+++ b/docs/Tutorial.md
@@ -243,9 +243,7 @@ In the first page of the example, we used
To add an internal link pointing to the second page, we used the
[add_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.add_link)
method, which creates a clickable area which we named "link" that directs to
- another place within the document. On the second page, we used
- [set_link()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_link)
- to define the destination area for the link we just created.
+ another page within the document.
To create the external link using an image, we used
[image()](https://pyfpdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.image)
diff --git a/fpdf/__init__.py b/fpdf/__init__.py
index e471ab9c7..253089cb8 100644
--- a/fpdf/__init__.py
+++ b/fpdf/__init__.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
import sys
-from .enums import TextMode, XPos, YPos
+from .enums import Align, TextMode, XPos, YPos
from .fpdf import (
FPDF,
FPDFException,
@@ -34,6 +34,7 @@
"__license__",
# Classes
"FPDF",
+ "Align",
"XPos",
"YPos",
"Template",
diff --git a/fpdf/fpdf.py b/fpdf/fpdf.py
index 37e234eaf..bec185f88 100644
--- a/fpdf/fpdf.py
+++ b/fpdf/fpdf.py
@@ -17,6 +17,7 @@
from functools import wraps
from html import unescape
from math import isclose
+from numbers import Number
from os.path import splitext
from pathlib import Path
from typing import Callable, List, NamedTuple, Optional, Union
@@ -827,6 +828,7 @@ def _beginpage(
contents=bytearray(),
duration=duration,
transition=transition,
+ index=self.page,
)
self.pages[self.page] = page
if transition:
@@ -1942,18 +1944,36 @@ def set_stretching(self, stretching):
if self.page > 0:
self._out(f"BT {stretching:.2f} Tz ET")
- def add_link(self):
+ def add_link(self, y=0, x=0, page=-1, zoom="null"):
"""
Creates a new internal link and returns its identifier.
An internal link is a clickable area which directs to another place within the document.
The identifier can then be passed to the `FPDF.cell()`, `FPDF.write()`, `FPDF.image()`
or `FPDF.link()` methods.
- The destination must be defined using `FPDF.set_link()`.
+
+ Args:
+ y (float): optional ordinate of target position.
+ The default value is 0 (top of page).
+ x (float): optional abscissa of target position.
+ The default value is 0 (top of page).
+ page (int): optional number of target page.
+ -1 indicates the current page, which is the default value.
+ zoom (float): optional new zoom level after following the link.
+ Currently ignored by Sumatra PDF Reader, but observed by Adobe Acrobat reader.
"""
- link_index = len(self.links) + 1
- self.links[link_index] = DestinationXYZ(page=1, top=self.h_pt)
- return link_index
+ link = DestinationXYZ(
+ self.page if page == -1 else page,
+ top=self.h_pt - y * self.k,
+ left=x * self.k,
+ zoom=zoom,
+ )
+ try:
+ return next(i for i, l in self.links.items() if l == link)
+ except StopIteration:
+ link_index = len(self.links) + 1
+ self.links[link_index] = link
+ return link_index
def set_link(self, link, y=0, x=0, page=-1, zoom="null"):
"""
@@ -1990,7 +2010,7 @@ def link(self, x, y, w, h, link, alt_text=None, border_width=0):
y (float): vertical position (from the top) to the bottom side of the link rectangle
w (float): width of the link rectangle
h (float): height of the link rectangle
- link: either an URL or a integer returned by `FPDF.add_link`, defining an internal link to a page
+ link: either an URL or an integer returned by `FPDF.add_link`, defining an internal link to a page
alt_text (str): optional textual description of the link, for accessibility purposes
border_width (int): thickness of an optional black border surrounding the link.
Not all PDF readers honor this: Acrobat renders it but not Sumatra.
@@ -3464,8 +3484,10 @@ def image(
Args:
name: either a string representing a file path to an image, an URL to an image,
an io.BytesIO, or a instance of `PIL.Image.Image`
- x (float): optional horizontal position where to put the image on the page.
+ x (float, fpdf.enums.Align): optional horizontal position where to put the image on the page.
If not specified or equal to None, the current abscissa is used.
+ `Align.C` can also be passed to center the image horizontally;
+ and `Align.R` to place it along the right page margin
y (float): optional vertical position where to put the image on the page.
If not specified or equal to None, the current ordinate is used.
After the call, the current ordinate is moved to the bottom of the image
@@ -3540,6 +3562,16 @@ def image(
self.y += h
if x is None:
x = self.x
+ elif not isinstance(x, Number):
+ x = Align.coerce(x)
+ if x == Align.C:
+ x = (self.w - w) / 2
+ elif x == Align.R:
+ x = self.w - w - self.r_margin
+ elif x == Align.L:
+ x = self.l_margin
+ else:
+ raise ValueError(f"Unsupported 'x' value passed to .image(): {x}")
stream_content = (
f"q {w * self.k:.2f} 0 0 {h * self.k:.2f} {x * self.k:.2f} "
diff --git a/fpdf/html.py b/fpdf/html.py
index 293e7e425..57cfaa8ca 100644
--- a/fpdf/html.py
+++ b/fpdf/html.py
@@ -807,8 +807,7 @@ def render_toc(self, pdf, outline):
"This method can be overriden by subclasses to customize the Table of Contents style."
pdf.ln()
for section in outline:
- link = pdf.add_link()
- pdf.set_link(link, page=section.page_number)
+ link = pdf.add_link(page=section.page_number)
text = f'{" " * section.level * 2} {section.name}'
text += f' {"." * (60 - section.level*2 - len(section.name))} {section.page_number}'
pdf.multi_cell(
diff --git a/fpdf/output.py b/fpdf/output.py
index 4cb7c819d..30807d747 100644
--- a/fpdf/output.py
+++ b/fpdf/output.py
@@ -226,6 +226,7 @@ class PDFPage(PDFObject):
"struct_parents",
"resources",
"parent",
+ "_index",
"_width_pt",
"_height_pt",
)
@@ -235,6 +236,7 @@ def __init__(
duration,
transition,
contents,
+ index,
):
super().__init__()
self.type = Name("Page")
@@ -247,8 +249,12 @@ def __init__(
self.struct_parents = None
self.resources = None # must always be set before calling .serialize()
self.parent = None # must always be set before calling .serialize()
+ self._index = index
self._width_pt, self._height_pt = None, None
+ def index(self):
+ return self._index
+
def dimensions(self):
"Return a pair (width, height) in the unit specified to FPDF constructor"
return self._width_pt, self._height_pt
@@ -372,10 +378,17 @@ def bufferize(self):
page_obj.parent = pages_root_obj
page_obj.resources = resources_dict_obj
for annot in page_obj.annots:
+ page_dests = []
if annot.dest:
- dests.append(annot.dest)
+ page_dests.append(annot.dest)
if annot.a and hasattr(annot.a, "dest"):
- dests.append(annot.a.dest)
+ page_dests.append(annot.a.dest)
+ for dest in page_dests:
+ if dest.page_number > len(page_objs):
+ raise ValueError(
+ f"Invalid reference to non-existing page {dest.page_number} present on page {page_obj.index()}: "
+ )
+ dests.extend(page_dests)
if not page_obj.annots:
# Avoid serializing an empty PDFArray:
page_obj.annots = None
diff --git a/fpdf/syntax.py b/fpdf/syntax.py
index 6b07efdbf..e237a631a 100644
--- a/fpdf/syntax.py
+++ b/fpdf/syntax.py
@@ -275,6 +275,14 @@ def __init__(self, page, top, left=0, zoom="null"):
self.zoom = zoom
self.page_ref = None
+ def __eq__(self, dest):
+ return (
+ self.page_number == dest.page_number
+ and self.top == dest.top
+ and self.left == dest.left
+ and self.zoom == dest.zoom
+ )
+
def __repr__(self):
return f'DestinationXYZ(page_number={self.page_number}, top={self.top}, left={self.left}, zoom="{self.zoom}", page_ref={self.page_ref})'
diff --git a/test/image/image_x_align_center.pdf b/test/image/image_x_align_center.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..99a89b620e9eb6fcb571bba9d3cfad5a127ffaf7
GIT binary patch
literal 28191
zcmZs?1yEf}0RebsaR*m>7ZO%@W;rV}XA)g@P?M@Y
zJhOtinU%4ag9nK&3+N3eFDDZl4+#$kD-#bdsP(%iz?_6x+1SF|8D2;T-rU~opE$Pv
zAyx@sZZB%;V&!1}-!e&cTBAQ2GwZw>$JC$ky}^LHm>
zduM>LlexXACkeAS=#7NAo0X}#s+1UL03dxpEg&=emlRcVX9rg&Q*&n$?*FOEKc)YN
z9{;-h-+FwrvUM?c0*%qu*u`AJ+|;Mk-|Axf#Z;EXloYVlurl2|dKcj{R
zJ^oV@G;%xVe-=}A0!_K8i-QvhD<{Z8|Gsf1VgJt)Xl|TI*jRZ;nE!9_|E%}_9KE!;
zm4&4X2^$yZ|FHxc2RAntJhPgDv9k>c*MFH-&DF%^KdVW`?w@)8d*ZZ|OsvgKUErBD
zt;|3s1oi#@v*CHCobvajRqoBC6Ygs$v?y!|XlUrxKUpy8a$7AlbP+Ug@N_D9B_(ju
zSAL>{64AV@;W8Z5m!H|ybiqFAxIBR0fx%x1c>eULC5gh|n*A1qu>k$!KE1mMZy=X1
zZFYK}Ulg?`Bou3C2W+&vSKqHqy_w34gx5J>L$;68m2dVmI4wwCxw~?Cdme
z`L*Zg_v6cEWo6~(=X+3YCY|AbCd4tWaQ_yA>hZmu;C{T=fSeDY-mYkE)&~LIjv53pZMUoGlZ8Sxtz(Ds;{pnCnvYFvukZ_b!*=s(3{1xC(GZ@JtF=^)OI#f;?#|XXYQ3}F`-dbW
zv83E-1-_1KW_&O1h9K~Nzh83be#d$W?t^_xEAc|5B`42sX=o^I+-UA>F0#04Y|3Kx
zY};I(-rJbb)Y3!S;FRRt?hS?=*{n<~5~d{heA1nZ`yql-{HuYcw>bnQ&w
zF|?c7OwxTZd~k*I-=+Jzx@Tz_^+GN(c!2rFKEO=`G`loBnazfYQSJciZFj$f2wGWL
znISb*@Dt+6Zni0|w_vex&i*No&{&Yav{7H&kjEB*?AqjRR;@GGE%r
zTFCRp?8lEEuMg)cSJcvW+YaKI&DHKX)<+~Hg)!X#1T-I4d*H$vfS3r||NS7vFut>q
zR<;ycY7rtdB*e+txpEh|p{k_B&IbFZ!`}3armp)yjPQG(dBz&IPFs0=_)6b>;Tyfn
zy4j^mglhZ_+{fdF`<5ue+2v)dBErvW6>Z(6=^5=cbmEWVmQ14T7lpPM#iUrnJ%V!~lb@e{pTepvdrYi3O904G}
zW|jR^?63{?c`#cjC$sX5QB2W;+QC9kKZf>^x!a7x2^4-rm0HrZBpv-V~gMgqnMz^Gn&P!1EBe)bp
zjm*a@Xa}ITKKsMV(hw9E7n2ihp5&oDR*7zPHUHI|O1ASdG@@g0-I!V97ttyhw3q%n
zs;q<7`dO+J9!%b}Nnw!k;1zPTef`$eY+ye#zEk!-{M2oYmtmMejL&;=ud}9@s!XQ^
zWuqtLDfKho^o;HE65G%xuIBwyO?h|w>F!wVxa5qvo8e=%#udqV5^{L(la7H&reJ}<
zk@NhoW-r+vZVob&I1N`*5z~>$$q(IN3|dFPPiS(W+P5DXgGJ}NhRH`&wC>M~iOJQc
z{s@_>e3~Rq>K6X9fnm@G#^!D@@K`C;T3>D@k%xmu+?S8p`S~+y$fbQ{2?(U5qz3aL
zurflGBK(c%VOxH_Sh}>)YdEYVx$tw2#*31NMz8W>CpuYDf*e?@*u(ljVt2Fep@cbO`)np(PU;&GMSm*32P?RN6;;4v=#
zy_?9xKB_{1iSVp%+`oK~W0?(S;K?xo!vJH0G5hqShs<_WMPQywavHR(IZ}iz_|%1<3VDx{d*t~Eoy70*5JYF)HU6*F0kI)vf`Wqow&sUsF1sk;4fG_2WP3<{Y{WL{
zGhgE%aZqFIl5)Yj?|o~zdPxI5IO4pe822w;X{WSwwMB59|oZ^
z@%T<%d8AkQw^^E-A>XFoo69vL9X@udAK1<1k|J`!1~a>#+P{?*LU3|aO-}TGrW>xD
z-kKlnf9JCXc?yWq09%DABhe+Gde-~*q5F8@_ogm)7UvbVe)^VnH#!rQ`X4aJY};gh
zHeR^EG>}Jkb8(4^it+)SHQQPKg)NFf+fPr|rkiS8g}e#QR+a+THrK7MjC1t}vxe-#
zscncEhIUJRAyvV{DMwYPpXCjCbw0y6-p<9cn7w&}k=I_^n16yt`clbP?9kGnEI5CT
zm5u1C^r$dgvXS=J*@HEdlvsjX6!dSk5pKmV{#V_o%e2|
z#^HG5Fe?eG-7OC^dkRk{Oc4xx)ej^BQ+H=oS%jx1H;laF0k8z5qt}KWh>i>ZS=9Uv
zFvIsjLZ(LQ$%8xOs&C}6uQgJx%9lt5pvl2uC*)alJWZQ|S{+XUho!YfUaV++D7Qqk
zjlAxn;MbKqeP_=;ErqzV%;PnLMv%ef(BEFCSs8RsZU7rFH->0{K()!7)pCd{^hFL%
zqvL}Mf=+dH5?3L4G-CCWst(WB%01%FM%Ds~wD=KD
z&d%h=M}|_+prm3@PVB5p6m&x5QadLFKEL3Ukv(BC8fv$NNZ~UmeARt?b)130LrHKghH7eW`SK{7uPVqT*@XnvcX!qK~*{a;)lsM$wFV_h*2>
zo`6;q@H6k+tv%OKbKHmS+_bWI@Qs9h(r5n+pAA-H?BX5MI~H(aZ>*3t5(&;3Fm>$o
z%GZw9bgp->`J|errsFX0t<&aKN7>~w2rn}>PY<9%R@WLjw6IFLM^x4+DBtO>FhC5$
zct0@$59eLyQ6<}k({-pSQlp;K%i0*ztiT}e@ao&5DZp^+I^}V9h1ke|>vL@A36#%#J~`UJE(pZ}v)BMt{@W
z3ownJeIc_q@HIWFj2qP&-1K6~I+EwQa5T@S@M)r4O%1Z#IcNo3S|7z2$P|9bQE26T
z>DU$CU2qJ4pfVi@Xi))X%*Ybqey={_IxH|`_`*jDn?dlghPkWw7mcSc#XC;30_~5G
zG;(~fSCF5mMiEHAcCFX2q;CKZUsd&_oQicL2ExPwHWdLs|6oZTkB^SNIJc6b
zgAX?~iJU?4S8a8@pkv$m`66MF8Hn)V2H;Q1GIoBjWJ3O#>sA_Fb8WN>Ba9it(+P`C
z($vIXod;&Ut8D*R*k|-=ci0Xfib>An-|g!PUwVF6b3g|ST<3X)?#&e|X*+W4$B2-=
zJNT*8w#0@=Dm56{r!>0bk*ShRK$Y4?5yoX2!BnEE>b_u9?u5Ip??dnWB@`$LC4Xmi
z<)p4nq}gMJ3%c8(uS<`SB1s8EA|tfz@CiLl_gS
z+xFMmi(!{GBGt;KMXPKGJ7!{7EMmnOw4)?$yoh$f^l^xiQB5t2deVE1x0NYjzVzC`
z85-z3@kcqbyI1Kp4puY#bB)fHd
zO>QanPI=t6+*p>>@_S=p$m-bRb&P?=ARbM@N?)s|G}lU?=E)z2Gl3QKl#fz6;)zgKZVZ!9++W$si#sB;pRC-y4_W+-UFj
zt*Wl4cjH;KO}6p+PK22-c%J`tM{8sGs|@04J7AaU$+87ne(xORak`^cf2WS+lK~g=
zI&kl@`_m7UPJ|(I6ssJwYp_vW&dx9aeUv0B`ww~})n%2iGP{oOyUj{u53wsEQ6pKV
zPJ@5F$j>~xdw2%vBhx^U^rFf($*9JTKzzIRBsKKCSJy-G>Y~-)`4=SvlpE3fd=(hY
zpH`yQJI*W%5`EtghC~pPrB^hyl_?QBQyS
zTtw2R7E72=gw`S{Y*x;ML?giKEDQr2J}cb`X
zRk0PlbLPvs9-I(}Gv^WVeQ~k0q&eZGzaV_C$v=*oo10q#zV}>}j1s!qUU0bC
z);_m)>hjqNX56_*07M|FPq}UH?KTVy)XgU^uYXEV%P4HqtN@aw%{g|n^9sIU#`wQo
z59dq8N@TmaKoMAEwd}09)6~RfG~w{c3WO@g1x*cq1Cq%7JAqYQ^X3k!&i?L35oxXW
z5GVGv46F
zZ7`Lkt`apy$uBKjA`Y?1zbX#H`W8YS@N~aqn3DXBS(c)&2_guS6Wq)}fVEPX&XzT%
zz}FfkK4ly3b;!DklX2-@i9C6up{Y@GiC-{FfAc~pz~LbIchz@LTqWt#(-yJ1M8m{&
z1{XsnJmlXh##r1|8yS%@!E+mD4F3+AMu;m6a>;NVS7S%mSrQEKC8!A38GQey^N(Qh)Lz@-2fmlNCo
zu)`+Czj*9X_ZbXR<5DkzpK4}%A-~AKM}K^LX#KcOQ&y40{EF?y%GKC(`izJaUV(c^
zmX6OBvNuf1nt@?cOU~r@pnJ;-X+XqJz#IGX54#UqY~DmRB<3JCZ16n7Pf%=B7%mS9fM;L9fO
zqGhAKI%N%lX2N
z*27{!3;X^;5DIoTe@Ro5+uogPQY81LN6yyOeD)<%|MeJi_kO$PXS>z|JP2Q3gt%l0mmA3FoEhFQ6m9XtncjMFo{Nhpg9+$~vsYX{3K{1`^7POpY`0%uY--Zp40NOWj_@gno2IK
zh34N|-wt2z+zhs6F!5+?0!}UYaqUK(E7LtHoQ(s1F}hO8l;X#e&?uv~?G7`7qo@`w
ztI5=kvCP>+2U$_(9yPjSfea;J?XyKriQX2=o;}Fb(ekKK;KqD@Ja*sS-fl2fUh~;H
z#?*faL}$o+$*HJ|@T;`9#nL8WPymB~7kYQVIG2*wcs~<=f0qsqR)rSZ8Sl@GZ{5Ed
z4eV!GuJmJ43a)?6=I+81%mk&MwWq6lZt|987(no(Q#n)bFjYO@#GR+p>h4+J^1ovd
za+zAFF*%l1f}YXhoH<1wyyJoX(`LffYdLHwBEGmp84}YpIopR(TR%N_ES)&Bx`3dV
zLFcvH$je-@Gh`sozY!wnmJsc7;?dYE}PQHH%`@4A~&c5wB
zq;Z0C#if+gn@1-uq2A>U%N3jip7!IhI9t?g?Jcg&W5i~835piL4{|b8_jRiTM!l2g
zIDDBx_o4|XD25$m-tU|U86g(qC^6G&zA2mT#K4+RMYCc=Qo&wVeS254tJJJc^C!u!
zx0|tnJ^8r4zBu6IUo0(b2Ak!>9jAkSmAw!J4+juZpMm&mt#CI>w*c&YRI@Ons
zLDUl`BzHzaV9(3!Z|Sl2{{9|5oJKYRcsnl6{#%4yIUXob=hegVeN73Nq#R}lN|{V_
zA7V@sPK%CC&__@32Tv2kq0%#p{r%4X6pkT~Fj%>w-zwr3(B=KK^i{KcmoU`@L*YHI
z#ee;VuX2SFx>bQ*cDsV+>Tb2W#WvQkTR34CgkNY-U-~MrlS3(&Twr^}SCJ39-}O+-
zm(lAutGL7KcaWrc#SB&cxJ^?)heL!lqK!$%w-Tvufn{LOD``dwIuPSC|83pnY&jijL5CPq^}7sFB-q2W}G*UkS3TNy>?$74RQTK
zQguTgGjlEJJ$L$gABIFehj0RH0X2tj1v{ZO9
zJqY4xx)$10Hq7x@hhKUhSLm3Cudh4gbgrVM!DwiVIhY@7Twq|LTH<3lov*I$*g5}Z!2=8xohQ^7mWqJr
zA&3EUBB$#k+$HlgBGPv+h2hsFhY+@m8FO}<+^uHVfGv!|jn0=JvmEZ#!sJ6WU9<)i
zWU6!B?*c75ZJ8fx?DzKO=7mpMvb~OsOb6NGe+(G8I=-(14&UF^rZ@7Fw!W?Ffnl_Z
zz#_vyS}}PZgMbq!VsG!A2J_}t!8a8BqL4+zG3v_>AZqFq-QnxL-b;n7=#QBoA=qG-
z=Qgw&H-;qb%vuzbV*%$#Rx`sZR{0Uh&Yj;lQIWsnTgBJOIA!q4M$(VO~H>p-}S2o$H}s=jT}#hrvCSpX7sJ
z_&+!}gUw4w14%_?#q@*23Lw0f2^2D#ODQlS6M;YjVZUEOofjv*G+&MpwotOOBg(T^
zY4VG?SyU%$q`GMUaJ^iO6;fRNh_ul7d)6_)zY#EwKN$I6lBM9IEpJEUQDuPVVG7bl
z@?mit7jbzeMzcXMs_SjI0z~N{#@2Mcv?S!~DSc|jt|?cYTJ4rMvA$qr8_l2HJ@qb<
zYB*+%2W57fhb@m|Nv{B}x%w_jRYn&CU!X<;dt4jh
z*hMMPx=-f*^rF_sPO(@cdMBq>tl}fvF?TjRL=<(_R!fkr2Yb$Wf-*{3xpx-{i8cqH
zrtJky_GGi9HJz9=xZyBN-mg+gskm!`J2VSAYL|bZTw~di?gh
znBcpSM-bv|wRsgzu(ykg@0Jp5F!<%2D>B+C6S9A@S#jlk6HGi<2YouOEcIIduV>G>
z3=R2-?lW+xqvY
z5u;J4p52MaAbU6!ING3o3A4?DOQprHvSP#Y&`B(Qjy)4=G?TcXNrw9-FY1n$)GV8*
z+6e~1YGZw%;7LZ%{F^3E$Fwd-C}iz#Yk{Rd8j3#wPKb~`+M(pm-$LG_8XX&Z9OH{-
zhv}&hgmYj(tn{a+}J#QX|N$1Q9}D~$*bdIJguzUD~Am~kEO>fB#Pbtz?O
zJqZI$r9uzw0u{wK31Z_K@$a?RZYgyZqX~6!f{cE@sPfs(9^4T!-KZW8ALkr=n43!LulYxWMyAYt?5vI~rw)Ts^fvy0|Hf?K4d
z4*GfOYpHfY)pJ4)9ardr;;^+@nBd+cN~_C7V0Hh7ez`Xi>S}x29~Vs#)Adsq1n2U(
zXGsGAsO?lxc8skwX7D}NBMH-&O;Hb8t`ts
zh=GwPKkoF6)>kTN#i3&5byA|rkR6sx<)pzcQ?9$vlVxlP6Bc;cEIh84MZMuZFP;pE
zLM#Ycz$n8oaMl*b!aAu}M7hftZ?pO3f`he;LKq&MJ0w~<8Aa8oHa|tnG=;BRmwQWr
znc!SX4!Hq9OF!HfV9t)n0ZY{1?O0o}nJkfYsSa?r?}G?2IsYK+a2m7p;Jtk_kvGT8
zd~+|2Hmk}O_9h66$u)MpeGRB!D0)o&*cyF`xM==fn{+qmvIE48B~bovGBXu2IFHh@
zUOB2-Z{ZZDI-6n{krp6x>H{%=kISd5$WyLasDyX)P&V*|oGXv2&HK?FP2~>66cU
z(M*0T&(gTxLcHR!8%RM_edviQ~ZGp^h&>@C4eG#X7dPlx|}+zZ@Vl$PVD0
z0dMEcTW~)3iW9UV_xz92kClEucCa|4*;Af=E=v5u+xQlRYV(XZ3~_-*d!@$t$}FIG
zSD(8Tu{GG1^-_X!ViA-<5kfa=ll1bf@`fr(tdy*R*RG<9*~uB_ON_v)n6T#EFtNWp
z8A`Yq-4_|(iaWb)<~gU^dYT9NT{ef)6=V7yxXz!
zF37Y9GJqR##O--aONWRuI7GJ^Xkx|dTGTOs0+uoYrZ%(BcZRa$(g01%nbFKJ=H$FC
zMT?xmAe*P3cQd6%hM_%i9kI*#6_Maw5W!UBHorXP934Y4viUwz$O5+$x8n}=pK~y7
z)(Z~brT)T47gw{V+z=rQMXYF|8|DDhvo)ozt!jns-ekyDEOdaiO?pGVmRCQ#4
zOo>^RmlL$A&662;EOkgsf)Cag-+nqailbR>NIafQP3aXn0Ych``eHrIa_8|U@;p@kK0
z>%@?O!2`;wY?e9X*dc!hu?`?d6>tVsFS}0RJmE?af-?_>BI1xG%YW-!UZYJWU7|za
zWA)bS8X*l89`w^f
z73`aT;KqQ88T^h}G4!N#i5M(VzF4b4wQG%1n{KiCTHc!sp%|*n-s%BIjEIx4rS`T|
z&iH2u^f|38n-|z~d4>}#w}oPVO2En_ETY@Wv&E#$44va~^jRLh^ixG9A|~Y$g;3rS
zOwNp*-re0%jM@ad`_EN^0thN8`h{d?5{S#%T@54i$O0;_*(LC+31+9cbW!@w=%iSsF6`
z189-to=Q$zA;ept4%?8uzj*|_l2s|-U)YO$@k!6ZKNcO9aZs;L7hHqNQ>a0K5UVrZ|0I8zh_YiRdqB5Gw?EY(A*
zdOEmuD3X;nTZuyUR|7WL=FMsYL4HkNN&`Vi2dg|r5Ai)+e#?Nx*C|M9h+u`XVl`!Z
zSX`0a1~NS}gL9ifb<@NH+M>8q$QO^A&)e)z3Zh8nJ_XxC)HKz8`H|oQ5G>5}s_yx>
zA?#1YOGuO>WF^8ZZr*RYoKi+I#Fc_iOh`<5RDK9cOoToe4yCRA0>pb;z0n@Z&;zHr
zyW#mjQ{%sCWe(HX6(2u_00ac{A#d{!-L#u7YBX!HtdFc_V=+KfCD!H~)zN;3^iq2BO#!G3P3RGFKEgxl#!ymL
zNMT+2Ds^a1(K}DufmDN72m2AL;RABEj;@b9NHO7I6}FanBZRwolcdoW9Qm+O!-w2P
z+7>93%=1!(_L;fBm>WD;YUX%umFvTiw&L%eKwJj|JM)YRb1kO&GcoA`T{&NPL2X-G
z)%`|R0#Cmn478-1*F75n>$aQ{Df@LY()iV^N_wWE&F?0&q>K?F65nwL)xF+xJzxgs
z+?R=~h=8P?3R$`>ic46ro>#TZta&`{rfn&l7eXYRhmp)((hL}!Y$4=fI=ixiqLnG)
znOY}UCA;z4n;azAG0M_Krds%`Z7ytJgb!mqMI+;5?mD>BP!G&aY&N`H3n;c!MO6gO
zge1_W12+I1?vY>lelGMbMDJsFFdn+Px@3XU7+5i;raIk7)`ydFH|e{PrMfv0<&JVG
zfAlp7zl=QP4LLup*WIpGe>Vu;J2LuOyk5q9kzPUC?rS=6jc`{_sUjyNXR@#!GtPx9
zzLKwv@IeaHadT@TwWhq3P~CUc;!&*(66$4du8{4px`z@S9Q*-~>cTUl-v@5vCa$V)
z$RN%>XsmmDd|W>1FTY&(U6TlBWCwXD>|J$tHz(Rr=F1L<2sZQz*l%D=>;h4QBuuV<
zeIaPo5IxaqwmK>E7_JSqDEKuzztSekKx6#+J+s~fflARvJ&Xw%V8l80TXRPqZp=N4
zXL!cqULFqU1g7>)wpdzT2sjeI%Osb~!1@7S{|PFFt*oR;Gjy>8?nN3^2622;J#R1%
z@W;H)DYcqSgAdgGTo`Udhu%XK))~tJdc~q>pIYVez5PvIzCeX{oR|^8`Z{r=uDzZW
zBq2bpygDyieB`Qbdzt{ix=2zLv)_H+`2i>h1We@mqRwu8D3`skUWVfglED(S5QYY<
z{D>db&EU2_bnhLHO&5)r5kqUan|acFH{J^wr9`ja4}}+y`?!{n(Q|!`l>vO^wo}dC
zPS_68Wakm`{~)l)SHh1QMcBgx&M?>dDos8q95aJU3}xz?Egj&_6Y`JU>z(8!|Eo=i
zjFq6w(vm&E0YNS8MhJxf#^A=$3}slepmQ5`o-R15P&wAZ=q0hX;UQLme8bE|5i(>p
z6}pxXGeaT5(_(2y-7uYp&~kj4^o_m84AnJ~+8h&udT%nO$251_T(j9NL&KB%IVE9A
zs0cjC0CLLE{s)Xpt=adZ`(xOTFqK;ClIndYhfTa!*zm(6e3r`KLY8DAu0_h6p0FFQ
zu6plr&HlpHMViEDBcA;bjWNVlLL0IJS16v@ROC{6KC{Q&Y3rqycJG1%J~rAisFxMu
zTJMZPijUd7l;vbqO&Qwe{=-L@unk&<;~YmrlP4E1ojDr$kN^fDcS9!;Dpdoie>ySi
zq>-1#c8Qzr5)N-{n0DO_E@hsf-^cf%RdxBUlW6Pn7F}R8<#b@p5hwh;K&_`Ksjl$!
zlR32v3j#{N@<9+7LgDYp_S#rIiR?y8y>p~%5eT|vVZ}NOteEWdv4at`uqEo0gzU3m
z^O8|~+t_SP>=;Ni#AEVZPG6(Kt1`)AbGzK^gfhDR1y4ZBs|RnO*>&3;{{^cm!;%2|
ziu9#$P>Voi%~D>YX`g9`n@k@CZZ6cKCzn^k>=wlOQ|XDrukIy6lUk?bZKuAgDH$%s
z4YCo3k)<9dCc=%`^8f5qNTslSY$wWnk{j8%J-R@}KGV}c@69amBnEA>!wvuO6b?4K
z{$A5e#&7kJp5R#_(SJztSJJ^n=7#LUndMB}VmTU+hb=x{UYto$VQtSq1juAGfX|K+
z61JShSLfuzg^hlMGYbV#aOYk1gk}m#v}V-C84}JqLrvAuGX-mV4QiTS=jZ3U`!;c9
zND3Tx$k)}5j&a|b3w$oa0OJCm;RDL(3B*-UQnE-#dY=HqY4p7_J091SxrP4jW+#rMyHzm6_Zy&=o@)+tr&DoaXQd|w~V&d%t1@kg0l-jvx`HF1&WMgaT1m&b
z{C7MDniJ2K>ANUd@0Vl&1^a*pr0p5jpZQ+i=Qt_u-m$5NuBMZ$8Y;&+FmwYPP6)S0?d-7nE^>MFPn{K{Q7P3qUZ#dw!9=K
zCt&+ef-((QKd}`U_f?EkEx3i{P~A0$jFz_U~o?05nUSV
zR4%~^J#;`Mm9JN=CKHJhvgb)H1sbZ#JM6^}6I3H66@Bsl{P7qCwmSdMv||{
zxxu)44Q8^&qMGM9;#O^gVSePrjVHs(?n;$VyVM0+e#k^KQ>*hv#Z6#&ik+?E=%Jb6
z*GfT;W6C7=@LOcNkI-8Xy;kW9k18{m1~H;H{<6u~XpC=?q8|EMI-_ANTg1@ItWWXc
zIe#lg2tMLIh)v=}a(K3FA%nv0up#;h?RaU4Ai?SAeY@H|Z2L|geaXdWQ@Gnc%IzN6
ze!V}E@GOzfMqv0fY+3i3c$!X0$!6U7(8p*6G4YbF;~QA<9Pjjz%s3{S{Sxq0<;J;_
zG>wuTt6+01oVD@N@}TGU)T;tS{V~_dg5IQ|xp*U3aclqGM|0xW?-7pR;NaWPLG0vh
z=?kK&=(3h;Peqy5@1e$Wz@|yL6Z>j54Fx^uHWXY8QLZEnU`v%p)-MZTgXF>kvhR!B
z1+m@36&%`~V0aJFfZ6u%aTawANK#hL*D;{#!g#r_9e9kPPi_)rSgQ;k$CefyA#iz_
zi53AqQ%eV4aH{MZ{UTk!s@vs}HN#*pTthk^-!Y8Q;gW~WG5m-u(xZaj4w^yfM)b2&
zho|0pG>C^+2t_cmK`y9erM-eifQ}9fuL#&I_$x!1fhURNeOU|!k!R=Q})|K1oiUIA!i+gY4-
zJ@upq5y+0dL^4S6jXaUpCD%gjlF&gd>zvy~46sEH7B(I{MnOONINj
zoB+}GM*c>z~p(9(oAE;QFc3zm`!F{M?pc}mR
z&u;;Nn~s)M3YC{dqI{B0&ewyKzv`EglIb^7{SM);Bq}CZ-dWd8{CO@UzOqmi-jlnS
z^m854(NDF9JNSK^+1LP}8XFo!pp6g69fph)8zwGa75K0qEl|oNxLoL=k?*zTelO{9
z!r)83!{{{IaElN^(OE;F(=7};4mo;O`z>1*W+%4@V2k0kO(qDhvk{bH2Rv0$w0=u;
zaYtsBjl;OCynCWd;+ADv*u8<*izw)Jh=jKLi8k9qe%=SDI#Vx4>&Ap;M{blDD%nI>
zaPGCi?ZCfHbO5DL7>pRhs10}uOtl=ePMfjd6*^&T7L{7pL*aj-CkoGqGO`cmDvUre
zosF3>5L@9(!GY}1W3!s$%W?X
zyWCZHG!_Jp&!TZd@uNKY)LU*#&xkoPXznRMdJ
z#xOEZK8xbkV`)-mgs2I^tLYdrle@f0zgA
z`obf4*&~SQfmeiLp#VA=O=V*2_&ar{^V{TOZCa~CP`Mg3LD%w@`2vfn!UAmC6sju_v-MQ~v>-zkLf?m=4uG+r&FQM_XGAHDPVymh->h&W!fER<6
z=qXU`*kPGFZ>pZ^S*7#4
z%z&q;yw^Qylii6ljr-C1cgh;U{^@Kp#nm_Hgfz84l`qhRs4p8~a&w%)7en_kUTr#L
z)XwI>&jApHJ9tVt2URq!)WOPum+i|r)*`UHUe`KwV18~c!G|a4=C&~h8rwNg?c`D&
z{!(?E+Z6&WviKt{ML5L>b@G;MW$9UR(9M{Kega)Zd!Bjly$P$bYLhV4gS&dArMy~z
z=WDweI{i
z(=Dk_S;Z_yBB+f}?54kH$+gjOFvM0|H}h{PJd^-o^l*38gju9VxG{8l+5QA{cvA&kcp=k_+&RoZ>9U$Tv;&m|K=haCI&r@Cj1I<^l*-8oXNQZ5
zOG3TY!cR&i?8=l*{mE$EC(i2=Vj^?`5GPG4qnjVU-TQ0SPW&~T9oun&|6RG`+Bz75
zxI1l(-ka*cwoS&yUAY&(xAn3-P!p)E+bHVVfz2FSMcDYoxIY)olDGTYxnAlY0C?rd
zl)K&f{t51%jkXNZ62mlY@FYHi_kPnL@)FSXDR(tT&fgn*nOqvgl6!GO;DtI5VEgkR
zfUC=*^DSvLcTcV|%`f|Qk;YTrQS`Xr6vUAeebS0gvsw_fnMCM)4iMhz0YBs7%BCY#
zsDazjJucap7lva>ZET%_3fe6@T^`j8ll#2V+K~<>%A$Vm29i$4shEq&pFFy!?s)893BxIXMA>4Q>S#vN0O
z?s=I=T7UiA;`;JdcO$zcV2bZX1PaDdUoumOhq<}=&5ra;-+BZd@UFI_tG$%K$|z<3Gq2&f4PRBge@_}(EA$!j^N
zmX{wsWonaC+RFK^UDbgCigK?n|~7YGVYJmao(BqbEG
zLgk5F=SNE5JeS{fqj+FfbMhIxC9^9&}ID@5O
zXp{-M7|{aJCDeeu^ViO^4M)Xsj4tRLJ
zc@=mZsrvCS04Xhm?S1H3(57Zt1i-S+S|jQMeKv1k5Z)OFrVAG-7*h{`SqbQzSftau
zXmAXh9iDT0*H7I)LPj{{+$URmOl*}=VgCbu2cGP)gRj+0N*hFO?_G<^IKWtSSr<7R
zRA~qIABG3jEEg#2zOHCbA~#c1*M6~k-OS4#dGb9-f=*5^40BHN@CwV%Wwn;9F|dqY
z+1wQ3=Wlnl=}D?Do0Gq&zI}bQ_46c@>$M@+hO@S@sh5mj%B%a+DN7N_552T|>|M1f
z3IgihgW_kubR*a)obNlVT`(mH-zl5^7`X>KNs%2{tKqFTfl>Ylhkpd_?u<5z6g
zzWm!p%?`}Xf1_u@>$|*jY703V#$Mo^p^eUyTa77emzS;s$;)FIs>ddOHn@=P`rux`
z{K)v!UcRj@Vdew*#pETCVy~VrB=+}5t2=20h@Pf1CUR5M7Ai^nCpSSt&qbTPTHDeH
zXDD2psg%ohoqf;<@Ce6>CRWO*#5^A#ua{=Oc8m+{WHZ_^{j!o)(ZzKbeSwq(TOPj-ICO3^6PzGe<`lV14<5&WC;TUBYUQWcFd++y<6Y|&5h4Wv?j*T
zj?;N!e7NiwcONm_t4C~on};3U@^JE|ZD*V@BWC%PX7tp>vWUT61mBsNgKE3xBE+sgR_y2(p+-D&)WS@6AcAk2e3jn_=Sbr=IAeg5*(ED-l1RJbi@sihZnm7f2a^Vd+f+Dl6r%^x0qIfgF*(+s?yfv0Dc$q7eI
z(b;QUZbjyw#+Tc@6R=1Q#6qi!?Zb_Y?WMlt^V4B6w_bTAnk}D&F*y-(=}&rEdO`ff
z>%91dhBSs{B@MOcuZ%9jRNS=1HiYKjNO#pcD3n!rXl)~aqPN~cM&@X6>Gopw4%ggnJ
z?2MG+uG{4!8hFdyFH&@_(7a8s=@aT8G@92DFI383dz<>c8t>v2JEfx9%8Aqcv5_Fd
zn$Ncr#D;!DIMg|}{odN8o-a%1L79Tc|2a?ZMVfv+{<{kfGO{bO&;>quX&`AuUT>|D
znhy@^a($`R!czQb(Y%NO0HTcQ&|OdZr3UZXvgLv9vQnYPd_R$uQ1G7vL7{Z4wa?i`
zS7LAUoO)3~5o7dvYu>rHfiu<#{F7Vd{<`HQH!hcb{^1j&VQg${vh;MlTy@T0txtNE
z8G2RdJPL2bfK%op{f4S4+Ft7Pe}2-*J2bBjg&j0e`wr
z`&&KnS@aKVf1*z4J5bEh#d6tMT@e26(<4|yODJR{?WvOcLpd~cYdbIarX0f`W3{k&
zhTNQ}XpFtjY1K1O0=i;1PLG&_u=t2%;(z6HvVdcECu7B1pfI-+-bkGkpAY2g?6gcWw!xvJ*391?QS}CI$_WzkrVW>26h|0&KrlDHnl;+xU1Qz
zdR(@7rEA}M9P_zznBzN|(iKVD#KwlJ1HGaBs;ZKGepff1LqYMsy6uT3H6an}d{;R*
zU(@y89sp6q^1`+ji9B^Xw)gkV*mk4~t5#co{D@;KxU8{L>>+kTr=s%=#&|ZsCYNneL96v-K+W`52~_-O
zxk*2a17yMP-|A!u_6Nb;NZCXZo6ROhM25~acWSDszUP&;w4`33xOG-ra3^+0)VmwW
zX}`bBng|AhVz57|JuH)e0@bA+`^`7(jXaDU%D$qW_@wC~XdeY!QXWS))sb_>r&8skN0}>X@c4ZOrA{;fT#2)MsUGi|JtAYtB5WNR$b9YeA*82T!
zaDif8F}1zn<_1CMk+6)YosW1AswItX26Txi0cIHcf35);c+1y2)teV9+~4-URhq!;X_it9(!_drV+UV%0S3|q{`j>nB{yO1GyWXc+N
zJ}I56-Tf#WTM7Sqh426iJ|EaLFJeL&e|Iq}`O^6*KRxLW_br)jwNO6h;zIf~+lk1G
zG9!=e@aD`Fx~y4|2==j_xCLo2Si%Q)_RQSR{!qBa*rRnm2|v_E8pHGEI|d16OOL11
zGqn{*U2!HcD-x!XnZBU^q5j5M;m{O+wVGM0>*mer3JNwQY(bQ{Zsr~Bo`G4)v=!({
zGj(CPKO^BFp5vwf@!Zfxq$>^&4
z_SWGShSbs$jlS`b((E~jRC5K`85xl`37jn)EVj-aovFb04}~wIPHhRjKoWo>jz7%K
z&Rz*>e|Jp$+uPcM`bNRfMiHmENIP4Zs3_k1)(rOT
zX#4U}x?T7wgn07k)L%_wnnN~Muhzu(bQubi?J|C9zhRL{}}7*5BCbOC7_Cg3kgWBLj1lQ7#5>q?TR=prc4UF^$Nge^IFXz
z0dFu-9BG$jHv1U1MHLC(_7|eC2bW-
zwOZLeJo5Mhi0+}Cq`7MZFOd(&w0W^zp(R1miIb&`v*vH9z@N0O7TOM?a{9gfAr$3)
zZr<{7PU11_Ufo24@G*DvskqNWi=uks*??SjsbIa;KYyG?w!x2uBc9dywKK=6QrH81
z!^8Jd=DK~1M9NO&S8dJF_H(O?E$Vo@^}YN3OxP)?UVbITdhHGGf?S&Cn3};aYbr`4
zwfL&lmdeyl-73t{%c^$Yuho09Q2G`0ZaJEZCVf(3q|6!Grx&=@0!SPl?l9KMq?}r0
z=US^7FS0~5?%semGB}PT-V@Y7hXM*cuPdAvp+`qY%q`Is;bi`s
zYr_lUNj$_9E1=^hI~>O^&?Ydv%%22?Fb|aHr(oyxk6w=(Vfv|cMBepuT1=j!xIH7X
zw6S7enu!F(?}D6@)*a?3MlZ=B$6F)6za`8q3uRh>ZIjIK)O$N+&cymOb!g)297b%T
zdXK}lKDwTVi9zqeYiu9uitBt~77vMSsuIa|euhAT0*tws2{uYWG}fCnLKVOHQ;3gI
zRi$i)s&e~A5t>lhZd94QDh9{YtvIIE1Tl}#mbqTkRc2EjWpumo3N0-wOL;L2kUuWf
zJU6hLN_jBN^v^IYKde&);(od9#XAu_{nZ?D8cW|=s=(iF85RRV%Nk49l|DS)*zoiz
zIv7ZM?>44qy`BwS-h{d^<3#?hJZgow#j$>}mYXV+wJt~Pyo-Hz9A{cM
z>w|AlEu0*Ys93|`@zkcGqN28Q4IFQE=ej3-57DoZTJmrXcB?Akw^v-OscJQ+xA8g_
zY01f<-7%rC1%AF!3RAU?4GuD4f{YPbrxz|;Ukrg0p)ll>Xi%;o>%2)LeL*LzX1%~F
zZNr;$#G&d2r0*`R47X%(n(@cJVvml?!M8r2I61a6PXXM8%UOXE7;4W5^YCB$DZjIaxnD}awO|9kS-4a#x)U^#uqwPr`8
zMToqj@+rYjX%By+l5R(Yu<;A6UD6J*-z010J$DA4
z=RonV;57t!yeLgrZ0pDLRw}C5nok%|5$a@gXG7uq_s
z^s+MiCh+5reSbUG&a0ENeu6016H>CqhY~d3Z%x*=A`2GVIRlIzwEEzwqn0m13QZ*`
z5<2%%`5W@;%bPHR3*r0NF)CSDBI?Yl#D^$wjH!isr%;qXeI7bFQY+qu4un{?B4qnU
zGw7QMouQ+~yQVF4zM7p0&lZ`aAMe+qDK#J-aX7c-%Yn3eD|l1Y7H&q_s=XjT)^%B|
z9*@Mj@29wL@>SOSZnhVP6!!~O(QJ5HE2GM(yr2EZ>L;ed_TDt%ospFShibKktZn`b+fs`eX-m5x>Y
zK9t-UML$Mv?1`KJE{P}F0E+Q)hz#3AT+~#8X&2S*jx^s#7op44j?s1dZ4IlY%}rqO
ztab(ZH#m*mUgkbE7p;xFXkdA>EJyrkG_j~^bGdmRJ-*z45b$)KZvl`bh|kJALZ9gu!){Z@{|vzd`m
zyI*kQXoYu^I?cjOD1nDSepT9vg|FJ{VW2kEQy(pT!Rk)<0H6pdg)p>W?YE&%m%G!~
z3>Ujfr}l8zucF1XYFHLFetmKOa?R`n8LO%?<8E=u4Co9X86C4^fVvZx~m&D)&c?Lh++agzT}W0M9B}(O33zK$hq!8y^2T>
z%!9tRnBph|YNG16uuV)%r$P;giO^>KjC@dl60#BSl_p`vC8CTqN1dp=K)5`wL5BB*
zgmXa!X!1wg&bw`k)XQx0;#Urzjf<9RWow~G9&7Kunz`V^zV#kQ1;U5!l1o^!)-g!@
zG79Xr@O{3jm1Fj)%Y~q#
znFp0OaI<3iL}xbE;;$&?))2xB;93Ae!C|8?G}OS}r5zV15s69N`)>e}`Ie
zsw8(QyyVuZyrQyJ0?7LhUP`yaA1U@mDc+=l`V)6S<28j2%t6X*E7!7C3J-|A7r+qd
zo9kpP|Li{N?D1n&aFxTwFY!e!7`@eynWYXgRz{Y#l4NnOaK*qO#>B>q$Xt5rWF6t3
z60?u#K<|&^hMNzS*oplp*fd=xVQ?~$P7fsNR0JqrP2wMHvq2SJ>Z8us2wzMErpTe-
zuq{ot)Ae+-RNp^%fMOVwK5qP%UIXca@qC%&*jH8`WM)W!NVfT(+y1s
zH}59HRm|oP$ByGhK0Mosg)#%gqSH
zyI`RLHFVb#iGgd+q4&@~^L?PLs&x1oS)&O$tw
zJ;Pi4bo;6=<=R4txR=?+?od^^{%*^(?#t1af^?0aGE=P1Qy!``SR*g0oy
zY;R}NQX?5axvtKO)t6>JV(8M6FU6`8wVF`!;ko`4?5k-f7gx&nNzC4yFvXU2G5&nx
z=XVd_OMv}#XVTwqkSeV?4K_oIR^+8v2xze3368)2p+7GalS67cN(Q{+Mtcm|JYHS?6>M-ta}AaZ};SEY~!N3UaVNSn~y4S)woHqeO=6y
z+f!D|YG|d+7H_V6O>c?)>aKunOVQ@HG?N&djv{KLe>H_(Irk#=5rq`km$d+T;8Ryy*ORh@NL}1v(I2k*=Ln!_BpbB~6
zubWl<<6t%z@xAv(Pp^n~{Gz7-B@=vNeO~!~=I_>0_Q`SbxfbPSn1+K^V)#JEd`s_`g|GJ}iJqSX
z#|a3gH@aku&a^%trKhKDv-Xm>x#IHS`dPg6$r7Lfp#j1SD0C_8g}~Z^gkWfKVF!wc
z4Pnj7_Lq5@8GMo+207m~&!-tyE+mIpX2v%!3SKrg>hJ8ZN-O7<_rx}(vkQe#qj(HY2Q5;%kJQ;o2%D
zB%PGh%(Rz~S@tGP4KLqlU&_iNz?y>GKCLawGMftNi*E||#?w6wlH&N#J%@Eit7Oyp
z{W{PDZcG)eL_!kLXQ&OkS$C|foJS7vtXleWJFn3x4=sC48zjZr@lV3Y+F;P*_j^f>
z%QdsgdG1V0r1YL~ZPIZeiJy8H?1=@OV{LyR<$V|t9Z()zGT!?IFb){u6LVEIzgB~g
z3t=v=r|w<7+3a~%{XOQA83o*#9>~G83TSwFRjgctpH^Ah0#6NVU_36Sg`@t$RGA2Y
zVo6$qG>K2M#+>ZG{N#s@pm#Rc2~djW*55Qkda!NTQv^y)f`LGPXcU5cGk+^Xp0%PY
zs`$CeQKYP_lDJX`AhTu4I2f(lXk%IBQiS&0K7TG?>^j5?ygz<+v&dd2UUfUGwX{#Z
zw<8Fc8c-x$S<^duwKeFVvjdGFb_0_?tpS+@ydO6xq>
z+)4g<97~Q%@jwS}+_9@Kvgo6+7X+;!Zb~z57Y=^x$piaPDj06&?*I@y#zFu#)%N_wS!oHr=Le
zIjO;wZ*!yK^NXshIkI_jDZxPiWHR&=V<@8!WRIQeT^>8^movB7?q<09I$=%RI^FPV
zV&*I9rMl1~GLQ=mP8T9rwgV9sB`^>sJKv2@ZzapyP3yBg@gcoXscN$X2bWe7T
zh=xbLj7oM}l_I>eCvkmhK5B#uSFb^(yC`X5wZnmG`x$Q_PVPzW}K+^E`8#A%T
zxU@HP`WVN-IiS|cx$$1{I%U?b$5!AgF0nxCmw`~s-8wp=G~HI5_mw<6Kw}%aiN(n-
z-q{q}_R0icly^7v1=2tNApV`gqE1Sr6b`6)x7e~(&~GNDNSL4D#VaiLskgZ)b=||a
ztV*JnPnRCU?H5b}QP;xpkjKGAh$IRYDbo0vc7&A?uNo
z?Q`4)0eiJ|Z(DYl5&5z8cVY=b2hom|Y1XEW#`J0`ogL?ga;d=Rr;X3EM0yc_ZXXWP%}XEgdY=cvCrqI;M)dJsaY3K06mN{5_2B!mIN7%k
zQ{O}8&|oo{@53h$CP7euE_iNK&vhEW~mwBqSYM2c0=YX`u^=WSkvI4HB
zLCyzl(?*-F*jL;gNjSG`Pj2qI5Vkf5?Aq
z!aZ(&k)k$pJXnoY^bsszlmdtRL>N9AeThe^VPnG-atmm~$)xGC09NDzg7fN3b*aDi
zz|Z0X`n-jb-Khvoj~cJ0{nu=vEf^O9XqJ0A8`E5S_bTuRJVtg1dWCPURID%GI5-y*
zkc8|N5$Mwv^pfaoEeLl1auxaX=FJ=Ppu1h5-1u9Yo%Be=_F9J#m8ds7s*sC3V^zhK
z-U7SipPn+rlx~ph(q|9Nc3L#S4Vf`#4s(Kg9
z({{%CZ-oeZfy}qh4qR7XY))c-Sz%TP!`>cAxzvYSb9MCzKsuZ!5eSj^YNQSf-z0cO
zmdZ_!Ggv!C7T-B&gsv?-P86~zB&-dV99s7|wDQ)DTXDmE^K_o3MB4Naz7NX>bQl5w
zvW(|Equ*`9LZXr>P*<-{uc;{`MX-0^y?C;KB#)T?24t&8N>9Oo@#O)IFYw
z`(Da!1g_&V5hT)PKPa%FGP_A9|02TRt$n93p${VcJVv3{7mq*~m&$6^yT%Yi{JHJn
zo+VofHD9|-I(OM_3l2~*Ed@MMx<)Cma?c{6>Y+d3Sj?54aW>f!hR4Olg><9fPy?{n
zSU`7?Jt9{jzACelyG2YY_O9iqXC$r414|OgV3y)?R_MJ_RT{C>N!N{A>jZnIFDhut
zHN6E5xIe!-B8yXGjkj=N9xVydY9Iz>26=Cv1@0+DM**ek*u-EFk$Zsi^yhMn`zkt`
zu|GMAT?3+C%#*enF_8FaiZho$Hm6W*T3$P+6*w$
zQUILQSfWHqOuixp30FjYc5W^r#$P2k0rIP4poI*c8Q=FP>X~b9B?>ZN$V4*eHI1gn
zjUr(%Z-n~cCPS_FcEj7a!9!ao^jKzHC)e?nx&88pZGWq8s?a6DX(J42+CK
z`1lZBGA46OMtsBsB3vC4)>{}?-0&MGpT3HYga>)mFf1!+l3VAIf$DU1KbRemsjRl$
z%$hRdGxlB^RKy)_B};j>-GW2BNZ1TP#ls{9i;6xROflG(s<3NZZu(qo$t4Xp+TUl3
zH_c8*%tl|@By<~_7&--kNHYP0_73fn1_M%`Tu$)*R^Qei82M$_@8jHSTU
z&ySpgXQ_-T^dru29YBaA{*GC8v>k)URT4I+tI0&8_?a{)hU9{Q?sXN&a1!s(G}oFD
zPe3}8Ay*@FD>VS@&h8BG&A?P3`m9DQ&Wn>hRN7A0`TcTQX*Z*QOY+Pfiw=nT$9Hcs~OQx1U@7k^DG=pYw=FB(Ke$3*<8nw{u$Q
zzkVG$ow0I8fAjJJ=EeZZ*>J`CNi#HxBl-B@L^~l$3n6iK9`lF+9Jkf`;xD6%@CBw%
zmL4tNg@me(9|mYe=dn8G^EJSM)bV?wdn3nG|Jrxk$e5#pDhWkn(G%7>F1a)Im;mS{
z`*fS6M1lbf^N7U60UHxcv5k
zV}1;F+N2kgOc0`ual}#8uiE8@K)Zb|zfQ+G`0#XwqgaCcjf@1Ze{HUdQL8^pDSc6~
zK+u1^j`}vs7yA=mbvZXXyGZbJz!Aj{Jm52LAAWYv5YNCQh>AwJ=}A#EL;xKrN^qDh
zvSCF=cmr-Nx2+i5FCYOr=_yCZ1-__#SX@E$F87?Y1NzI<2X9z;hXV^Hp$zxOd3*Z}
zx*W+RVsf54kdhmsms=!&jx1P1=(vlFq-(Km+27m4#>QUn@J>?DdqQGmf}y&DDUWW?
zPpL06nQ0wPWwagN{D>OBsY$*Cp}lv2afZ~YveKD0k%>dJ^?
z>919@z$N}NT^yX%?UPsXEZm#zi^O<%cu6!Dcr{Dpq~`0?ZL(4P9cBBS8_l(vn{?)UGQ
zp1s}dx4%-^U1zf^D)2yb^ZrU4c&a`C%dVL9#7Ox0^+Ur97N-;5oq15u^Z7YXSH{j=
z@kdPhenu53pb%Kl1THGQ0B$Gw*Jb^
zS6w|*f(z!tcOfNNw}u6*Nr{PEc+3Y|Z_8%T?#=<0a?BiKu#++oxJyHi2I@GNvabV+
zS?JM;jvcQ#j&XlUpY#g>QH9yoazxO1xgBy1xxxuEMUuY-q@jk&3D3aAyBFaP$7aWX
z26}I@!a$Zb99P-TU4V-cbVJ91gX)~w-f5wy9csUwfMS)2a!`G^j`bq2VhY6!Ae5eE<@fs&xf1V%yP+!p}r%Jm%0*PdL1nKywNECW-(f+|KkenBkiIaNR?Y8_R)EcvOr*sgxvx)CNVG`)lMW)PxFV?>aQtg;WRx|
zgUL<`DJGqN4U8FuH2ZIB~uIaFL_T$Ar{d7j>a>$sb0g~E(iso$qQjvNlmVZ
z7EITlyP%e$mf%tfUudcWgF1%~;P$#;1k^s&b)I)vf>?tp=q%3nH&m6^P34Rn(j<(p
z9)a(nn=TU_I0QtpF!>yZ&oB8SIk-^w+?+a}xB&u8>G+C{dw1iPFZT}*@V$g=diOc9
z%ADZ6y*=fFse2#N-JG#H7q`1+rl*B&SoCNxU&(Gatc*1LlxqE^u7C#3I_7a4;SYJL5m2t=9TgvgI6)xiYHYj$NHq64+@>~CIh2LL
zVL|tYWep9yv=hhI($8Uko)WtM;NJ%ikDL|#yOYCTPlW%pl=ye6h5wzCgMz!I@Bf{Z
z1MmM=D+gX-kPzVH@c(4q@QK@NRS`Ej5}Cu$q8F0KXc-$#9qwNy{%()%I);$$POr^;jfxf&swZ(~=Dplda#(UZB_c0c6ZpNBE8
z;j5Y%1uet1Gp8t7h0=Xz@gmP1IuY5-xnbe57sm%0@XkY^kAs(QJbUP!ODaSdM2>_9
zkm|WwC~K&MrV#A&@C%>y1D7Qj!*Xj*Qc{1N2WgPKCpf)|g3c%EHqBy(EhO4;W*fjm
ze%e7coy8iNs^mI2_0<;cYx)u{WJTR*D@&Y7~Z?(+M@i2lD#y6fA{R&`#r8qp@rE
zIj_!DxeBKM#QfUFxz^l-y2+rQNFo8%vFO~Q#0x0?k9Y@b=C{QCeYP`
zBke0+R971KtlmT9^dz2fKAEw|3Sx(5rsnpr@fiD#B*EeearyYEqi=RK>4R~+vqcGs
zr2e}}p?_;!Opa?FV6$T=k0vRNyzz$e*)od6eO#0c`)5f5_67J;Lp
zL1ACO`N}DxXzp@(Os;A-xj~)D_p9}bjV~<-^{dr~bMmz;2N`NtZ!br)g{e;wPE~Bzoyth>iVc4V^!9+Pv8=`1(0!=UTX}%P_Ne?wmtZ
z!ntm3>pK!2&3N_ImYSUvcv$Nn=T5(V<2z
zCwAi7r#Fr8SU@{ja$d$Y?WTV_p;Mtl2h~mfI>BJ?4CMwx5Or#@8}eI`W6@?nAhF*R
zf^CeuJMop`DDqfgl{Ts0xUagc1|&SrQQM3I?qCok=wsQdIYO0zx6E+9=0thTkk<0+
zxq{uvnF(p5SXrF*OmJ!=IMu!ikkwlJl~3M!XhPjI?l
zE8I@L39Nn{`?x9)Oln4^+h~0bTKeG?3fW24o5{fvm+ZN0RClG$EYH3hw{83Vm`nd<
z2!554B8U`4+Gp9($P!spQEkf=A>fU&XDe=|ks3oy2EMOWV?fuJ{SzKgKACJWig2l(
zZY-j|;OT||C~1^EdB?)BcUF;#;s-0*Z6Aj+CI=S;RB7oDe3Us4uK(6#zvmbxGvvdj
zrM9GW3VPAgq}xd7)X|E+^mIhy28HmUR1DH+CcsssnbUVzTrE#cS#ij6LL)G>7`mKN
zUKQFmmd9Y|Ho}R-MKo|}t=9Gt#Fh(tIdXV;bCk(q7llV9li`(=egW0|S+K3&C)VUQ
z%Mp0@VDR3T3s?+ytVr`wczZs1iFY44KD2!N>$@7Bf?d?9-Y}C{+gZVU38!ZBeARrM
zO8*99B)V{~Y%+?ud%m^VNm!j7lY1jk;1#p>NA3|c&g^W8?HmPV9e$%LxbigUN$_)`
zteN5|Zao`QrIMK&M|lXaY|E^64|>MGCF@X?M7g=J_q6ioy;-|yV)h*i+;R3zu+%YR
zDcIK?T9Gq;abS8UO_zdyN7CKN4wwChK;J&Q`!Ja=TCpiVy7|&9s$Ft6D4v
zfnrTmF~{oy!^X~~7$IkW`vxPr;^dyz7un59L&JWh`~yqloRU(P``mwI&_ZA3n8>Ob
zCz0ABks%UR;ms$d7{h7AT3gPl9B+RnzR-}J6=8~z49VD7#m7lb1(CD$RmdV!%59Y(
zTk3dAq!q}spK3wNs%g!*nWhOZdL^eq*N0uHMW
z>g_e5SQ#?2kclg@Zn{<{T_5@M*a+$
z%{et6)s5HKt~UWSka?3)6`!S55q)fy?Wg=~Gg>K4F1Vuy0ApE;?J(YuA=pMMg?%f_Uv}L}-
zc&lefQ3MWF+kE)=awl{V
zmbpppE?TxQJyYuWe!E?)nzZ<7A!v&=uAl>n=+e_A>HwU|=krTyzwr3H9K
z0e}B=uLA$emSq5stiPUNvVe;gEvu{uudtvnFCRZIuP_fV8Sx6U@bIv({mYwu+-+>p
zd1!^v|1SSu6RjW!#1EpirTwpY!nFTbMC<%t^Mrv=>+ke0^LT~-eLa3)OaF5{0U^NX
z?7zL24+P@*pWEXT65;_4?Z2-lBqaPV^E}-x?Hz60|6#+XZSQ9T90s?RiwoeH^|z7G
zxs{x4U1IzAyVNEn@oNlslJ{XYP?=ytRK
literal 0
HcmV?d00001
diff --git a/test/image/image_x_align_right.pdf b/test/image/image_x_align_right.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..b076696996d519fd55a9f14653efdeaa37791894
GIT binary patch
literal 28190
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