File: TextStyling.md

package info (click to toggle)
fpdf2 2.8.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 53,828 kB
  • sloc: python: 39,486; sh: 133; makefile: 12
file content (223 lines) | stat: -rw-r--r-- 9,301 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# Text styling #

## .set_font() ##

Setting emphasis on text can be controlled by using `.set_font(style=...)`:

* `style="B"` indicates **bold**
* `style="I"` indicates _italics_
* `style="S"` indicates <s>strikethrough</s>
* `style="U"` indicates <u>underline</u>

Letters can be combined, for example: `style="BI"` indicates _**bold italics**_

```python
from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.set_font("Times", size=36)
pdf.cell(text="This")
pdf.set_font(style="B")
pdf.cell(text="is")
pdf.set_font(style="I")
pdf.cell(text="a")
pdf.set_font(style="U")
pdf.cell(text="PDF")
pdf.output("style.pdf")
```

## .set_stretching(stretching=100) ##

Text can be stretched horizontally with this setting, measured in percent.
If the argument is less than 100, then all characters are rendered proportionally narrower and the text string will take less space.
If it is larger than 100, then the width of all characters will be expanded accordingly.

The example shows the same text justified to the same width, with stretching values of 100 and 150.
```python
pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", size=8)
pdf.set_fill_color(255, 255, 0)
pdf.multi_cell(w=50, text=LOREM_IPSUM[:100], new_x="LEFT", fill=True)
pdf.ln()
pdf.set_stretching(150)
pdf.multi_cell(w=50, text=LOREM_IPSUM[:100], new_x="LEFT", fill=True)
```
![](font_stretching.png)


## .set_char_spacing(spacing=0) ##

This method changes the distance between individual characters of a test string. Normally, characters are placed at a given distance according the width information in the font file. If spacing is larger than 0, then their distance will be larger, creating a gap in between. If it is less than 0, then their distance will be smaller, possibly resulting in an overlap. The change in distance is given in typographic points (Pica), which makes it easy to adapt it relative to the current font size.

Character spacing works best for formatting single line text created by any method, or for highlighting individual words included in a block of text with `.write()`.

**Limitations**: Spacing will only be changed *within* a sequence of characters that `fpdf2` adds to the PDF in one go. This means that there will be no extra distance _eg._ between text parts that are placed successively with `write()`. Also, if you apply different font styles using the Markdown functionality of `.cell()` and `.multi_cell()` or by using `html_write()`, then any parts given different styles will have the original distance between them. This is so because `fpdf2` has to add each styled fragment to the PDF file separately.

The example shows the same text justified to the same width, with char_spacing values of 0 and 10 (font size 8 pt).
```python
pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", size=8)
pdf.set_fill_color(255, 255, 0)
pdf.multi_cell(w=150, text=LOREM_IPSUM[:200], new_x="LEFT", fill=True)
pdf.ln()
pdf.set_char_spacing(10)
pdf.multi_cell(w=150, text=LOREM_IPSUM[:200], new_x="LEFT", fill=True)
```
![](char_spacing.png)

For a more complete support of **Markdown** syntax,
check out this guide to combine `fpdf2` with the `mistletoe` library:
[Combine with Markdown](CombineWithMarkdown.md).


## Subscript, Superscript, and Fractional Numbers

The class attribute `.char_vpos` controls special vertical positioning modes for text:

* "LINE" - normal line text (default)
* "SUP" - superscript (exponent)
* "SUB" - subscript (index)
* "NOM" - nominator of a fraction with "/"
* "DENOM" - denominator of a fraction with "/"

For each positioning mode there are two parameters that can be configured.
The defaults have been set to result in a decent layout with most fonts, and are given in parens.

The size multiplier for the font size:

* `.sup_scale` (0.7)
* `.sub_scale` (0.7)
* `.nom_scale` (0.75)
* `.denom_scale` (0.75)

The lift is given as fraction of the unscaled font size and indicates how much the glyph gets lifted above the base line (negative for below):

* `.sup_lift` (0.4)
* `.sub_lift` (-0.15)
* `.nom_lift` (0.2)
* `.denom_lift` (0.0)

**Limitations:** The individual glyphs will be scaled down as configured. This is not typographically correct, as it will also reduce the stroke width, making them look lighter than the normal text.
Unicode fonts may include characters in the [subscripts and superscripts range](https://en.wikipedia.org/wiki/Unicode_subscripts_and_superscripts). In a high quality font, those glyphs will be smaller than the normal ones, but have a proportionally stronger stroke width in order to maintain the same visual density. If available in good quality, using Characters from this range is preferred and will look better. Unfortunately, many fonts either don't (fully) cover this range, or the glyphs are of unsatisfactory quality. In those cases, this feature of `fpdf2` offers a reliable workaround with suboptimal but consistent output quality.

Practical use is essentially limited to `.write()` and `html_write()`.
The feature does technically work with `.cell()` and `.multi_cell`, but is of limited usefulness there, since you can't change font properties in the middle of a line (there is no markdown support). It currently gets completely ignored by `.text()`.

The example shows the most common use cases:

```python
    pdf = fpdf.FPDF()
    pdf.add_page()
    pdf.set_font("Helvetica", size=20)
    pdf.write(text="2")
    pdf.char_vpos = "SUP"
    pdf.write(text="56")
    pdf.char_vpos = "LINE"
    pdf.write(text=" more line text")
    pdf.char_vpos = "SUB"
    pdf.write(text="(idx)")
    pdf.char_vpos = "LINE"
    pdf.write(text=" end")
    pdf.ln()
    pdf.write(text="1234 + ")
    pdf.char_vpos = "NOM"
    pdf.write(text="5")
    pdf.char_vpos = "LINE"
    pdf.write(text="/")
    pdf.char_vpos = "DENOM"
    pdf.write(text="16")
    pdf.char_vpos = "LINE"
    pdf.write(text=" + 987 = x")
```
![](char_vpos.png)


## .text_mode ##

The PDF spec defines several text modes:
![](pdf-text-modes.jpg)

The text mode can be controlled with the `.text_mode` attribute.
With `STROKE` modes, the line width is induced by `.line_width`,
and its color can be configured with [`set_draw_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_draw_color).
With `FILL` modes, the filling color can be controlled by [`set_fill_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_fill_color)
or [`set_text_color()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.set_text_color).

With any of the 4 `CLIP` modes, the letters will be filled by vector drawings made afterwards,
as can be seen in this example:

```python
from fpdf import FPDF

pdf = FPDF(orientation="landscape")
pdf.add_page()
pdf.set_font("Helvetica", size=100)

with pdf.local_context(text_mode="STROKE", line_width=2):
    pdf.cell(text="Hello world")
# Outside the local context, text_mode & line_width are reverted
# back to their original default values
pdf.ln()

with pdf.local_context(text_mode="CLIP"):
    pdf.cell(text="CLIP text mode")
    for r in range(0, 250, 2):  # drawing concentric circles
        pdf.circle(x=130-r/2, y=70-r/2, radius=r)

pdf.output("text-modes.pdf")
```
![](text-modes.png)

More examples from [`test_text_mode.py`](https://github.com/py-pdf/fpdf2/blob/master/test/text/test_text_mode.py):

* [text_modes.pdf](https://github.com/py-pdf/fpdf2/blob/master/test/text/text_modes.pdf)
* [clip_text_modes.pdf](https://github.com/py-pdf/fpdf2/blob/master/test/text/clip_text_modes.pdf)


## markdown=True ##

An optional `markdown=True` parameter can be passed to the [`cell()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.cell)
& [`multi_cell()`](https://py-pdf.github.io/fpdf2/fpdf/fpdf.html#fpdf.fpdf.FPDF.multi_cell) methods
in order to enable basic Markdown-like styling: `**bold**, __italics__, --underlined--`.

If the printable text contains a character sequence that would be incorrectly interpreted as a formatting marker, it can be escaped using `\`. The escape character works the same way it generally does in Python (see the example below).

Bold & italics require using dedicated fonts for each style.

For the standard fonts (Courier, Helvetica & Times), those dedicated fonts are configured by default:

```python
from fpdf import FPDF

pdf = FPDF()
pdf.add_page()
pdf.set_font("Times", size=50)
pdf.cell(text="**Lorem** __Ipsum__ --dolor--", markdown=True, new_x='LEFT', new_y='NEXT')
pdf.cell(text="\\**Lorem\\** \\\\__Ipsum\\\\__ --dolor--", markdown=True)
pdf.output("markdown-styled.pdf")
```

![](markdown-style.png)

Using other fonts means that their variants (bold, italics)
must be registered using `add_font` with `style="B"` and `style="I"`.
Several unit tests in `test/text/` demonstrate that:

* [test_cell_markdown_with_ttf_fonts](https://github.com/py-pdf/fpdf2/blob/2.6.1/test/text/test_cell.py#L155)
* [test_multi_cell_markdown_with_ttf_fonts](https://github.com/py-pdf/fpdf2/blob/2.6.1/test/text/test_multi_cell_markdown.py#L27)


## .write_html() ##

[`.write_html()`](HTML.md) allows to set emphasis on text through the `<b>`, `<i>` and `<u>` tags:

```python
pdf.write_html("""<B>bold</B>
                  <I>italic</I>
                  <U>underlined</U>
                  <B><I><U>all at once!</U></I></B>"""
)
```