0
# Text and Font Rendering
1
2
Font loading and text rendering including system fonts, TrueType fonts, text metrics, and styling options. Pygame provides comprehensive text rendering capabilities for displaying text in games and applications.
3
4
## Capabilities
5
6
### Font System Management
7
8
Initialize and manage the font rendering system.
9
10
```python { .api }
11
def init() -> None:
12
"""Initialize font module."""
13
14
def quit() -> None:
15
"""Uninitialize font module."""
16
17
def get_init() -> bool:
18
"""
19
Check if font module is initialized.
20
21
Returns:
22
bool: True if font module is initialized
23
"""
24
25
def get_default_font() -> str:
26
"""
27
Get filename of default font.
28
29
Returns:
30
str: Path to default font file
31
"""
32
```
33
34
### System Fonts
35
36
Access and use system-installed fonts.
37
38
```python { .api }
39
def get_fonts() -> list[str]:
40
"""
41
Get list of available system fonts.
42
43
Returns:
44
list[str]: List of font names available on system
45
"""
46
47
def match_font(name: str, bold: bool = False, italic: bool = False) -> str:
48
"""
49
Find system font file path by name.
50
51
Args:
52
name (str): Font name to search for
53
bold (bool): Whether to look for bold variant
54
italic (bool): Whether to look for italic variant
55
56
Returns:
57
str: Path to font file or None if not found
58
"""
59
60
def SysFont(name: str, size: int, bold: bool = False, italic: bool = False) -> pygame.font.Font:
61
"""
62
Create font from system font by name.
63
64
Args:
65
name (str): System font name
66
size (int): Font size in pixels
67
bold (bool): Use bold variant
68
italic (bool): Use italic variant
69
70
Returns:
71
pygame.font.Font: Font object
72
"""
73
```
74
75
### Font Class
76
77
Main font object for rendering text with various styling options.
78
79
```python { .api }
80
class Font:
81
def __init__(self, filename, size: int):
82
"""
83
Create font from file or use default font.
84
85
Args:
86
filename: Font file path or None for default font
87
size (int): Font size in pixels
88
"""
89
90
def render(self, text: str, antialias: bool, color, background = None) -> pygame.Surface:
91
"""
92
Render text to a surface.
93
94
Args:
95
text (str): Text to render
96
antialias (bool): Use antialiasing for smoother text
97
color: Text color
98
background: Background color (None for transparent)
99
100
Returns:
101
pygame.Surface: Surface containing rendered text
102
"""
103
104
def size(self, text: str) -> tuple[int, int]:
105
"""
106
Get dimensions of text if it were rendered.
107
108
Args:
109
text (str): Text to measure
110
111
Returns:
112
tuple[int, int]: (width, height) in pixels
113
"""
114
115
def get_height(self) -> int:
116
"""
117
Get height of font in pixels.
118
119
Returns:
120
int: Font height including line spacing
121
"""
122
123
def get_linesize(self) -> int:
124
"""
125
Get recommended line spacing.
126
127
Returns:
128
int: Pixels between lines
129
"""
130
131
def get_ascent(self) -> int:
132
"""
133
Get font ascent (height above baseline).
134
135
Returns:
136
int: Pixels above baseline
137
"""
138
139
def get_descent(self) -> int:
140
"""
141
Get font descent (height below baseline).
142
143
Returns:
144
int: Pixels below baseline
145
"""
146
147
def metrics(self, text: str) -> list:
148
"""
149
Get metrics for each character in text.
150
151
Args:
152
text (str): Text to analyze
153
154
Returns:
155
list: List of (min_x, max_x, min_y, max_y, advance) for each character
156
"""
157
158
def get_bold(self) -> bool:
159
"""
160
Check if font is bold.
161
162
Returns:
163
bool: True if font is bold
164
"""
165
166
def set_bold(self, bold: bool) -> None:
167
"""
168
Set font bold style.
169
170
Args:
171
bold (bool): True for bold text
172
"""
173
174
def get_italic(self) -> bool:
175
"""
176
Check if font is italic.
177
178
Returns:
179
bool: True if font is italic
180
"""
181
182
def set_italic(self, italic: bool) -> None:
183
"""
184
Set font italic style.
185
186
Args:
187
italic (bool): True for italic text
188
"""
189
190
def get_underline(self) -> bool:
191
"""
192
Check if font is underlined.
193
194
Returns:
195
bool: True if font is underlined
196
"""
197
198
def set_underline(self, underline: bool) -> None:
199
"""
200
Set font underline style.
201
202
Args:
203
underline (bool): True for underlined text
204
"""
205
206
def get_strikethrough(self) -> bool:
207
"""
208
Check if font has strikethrough.
209
210
Returns:
211
bool: True if font has strikethrough
212
"""
213
214
def set_strikethrough(self, strikethrough: bool) -> None:
215
"""
216
Set font strikethrough style.
217
218
Args:
219
strikethrough (bool): True for strikethrough text
220
"""
221
```
222
223
### Advanced Font Rendering (FreeType)
224
225
Enhanced font rendering with advanced typography features (available when pygame built with FreeType).
226
227
```python { .api }
228
# pygame.freetype module (if available)
229
def init(cache_size: int = 64, resolution: int = 72) -> None:
230
"""
231
Initialize FreeType font system.
232
233
Args:
234
cache_size (int): Number of fonts to cache
235
resolution (int): DPI resolution
236
"""
237
238
def quit() -> None:
239
"""Uninitialize FreeType system."""
240
241
def get_init() -> bool:
242
"""
243
Check if FreeType is initialized.
244
245
Returns:
246
bool: True if initialized
247
"""
248
249
class Font:
250
def __init__(self, file, size: int = 0, font_index: int = 0, resolution: int = 0, ucs4: bool = False):
251
"""
252
Create FreeType font object.
253
254
Args:
255
file: Font file path or file object
256
size (int): Font size (0 for scalable)
257
font_index (int): Font index in collection
258
resolution (int): DPI resolution
259
ucs4 (bool): Enable UCS-4 character encoding
260
"""
261
262
def render(self, text: str, fgcolor = None, bgcolor = None, style: int = 0, rotation: int = 0, size: int = 0) -> tuple[pygame.Surface, pygame.Rect]:
263
"""
264
Render text with advanced options.
265
266
Args:
267
text (str): Text to render
268
fgcolor: Foreground color
269
bgcolor: Background color
270
style (int): Style flags (STYLE_BOLD, etc.)
271
rotation (int): Rotation angle in degrees
272
size (int): Font size override
273
274
Returns:
275
tuple[pygame.Surface, pygame.Rect]: Rendered surface and text rectangle
276
"""
277
278
def render_to(self, surf: pygame.Surface, dest, text: str, fgcolor = None, bgcolor = None, style: int = 0, rotation: int = 0, size: int = 0) -> pygame.Rect:
279
"""
280
Render text directly to a surface.
281
282
Args:
283
surf (pygame.Surface): Destination surface
284
dest: Position to render at
285
text (str): Text to render
286
(other args same as render())
287
288
Returns:
289
pygame.Rect: Rectangle where text was rendered
290
"""
291
292
def get_rect(self, text: str, style: int = 0, rotation: int = 0, size: int = 0) -> pygame.Rect:
293
"""
294
Get rectangle that would contain rendered text.
295
296
Args:
297
text (str): Text to measure
298
style (int): Style flags
299
rotation (int): Rotation angle
300
size (int): Font size
301
302
Returns:
303
pygame.Rect: Bounding rectangle
304
"""
305
306
def get_metrics(self, text: str, size: int = 0) -> list:
307
"""
308
Get detailed character metrics.
309
310
Args:
311
text (str): Text to analyze
312
size (int): Font size
313
314
Returns:
315
list: Character metric data
316
"""
317
```
318
319
## Font Style Constants
320
321
```python { .api }
322
# Style flags for FreeType fonts
323
STYLE_NORMAL: int
324
STYLE_UNDERLINE: int
325
STYLE_OBLIQUE: int
326
STYLE_STRONG: int
327
STYLE_WIDE: int
328
STYLE_DEFAULT: int
329
```
330
331
## Usage Examples
332
333
### Basic Text Rendering
334
335
```python
336
import pygame
337
338
pygame.init()
339
screen = pygame.display.set_mode((800, 600))
340
341
# Create font objects
342
default_font = pygame.font.Font(None, 36) # Default font
343
system_font = pygame.font.SysFont('arial', 24) # System font
344
345
# Try to load custom font
346
try:
347
custom_font = pygame.font.Font('custom_font.ttf', 48)
348
except:
349
custom_font = default_font
350
351
running = True
352
while running:
353
for event in pygame.event.get():
354
if event.type == pygame.QUIT:
355
running = False
356
357
screen.fill((255, 255, 255))
358
359
# Render different text samples
360
text1 = default_font.render("Default Font", True, (0, 0, 0))
361
screen.blit(text1, (50, 50))
362
363
text2 = system_font.render("System Arial Font", True, (255, 0, 0))
364
screen.blit(text2, (50, 100))
365
366
text3 = custom_font.render("Custom Font", True, (0, 0, 255))
367
screen.blit(text3, (50, 150))
368
369
# Text with background
370
text4 = default_font.render("Text with Background", True, (255, 255, 255), (0, 128, 0))
371
screen.blit(text4, (50, 200))
372
373
pygame.display.flip()
374
375
pygame.quit()
376
```
377
378
### Font Styling and Metrics
379
380
```python
381
import pygame
382
383
pygame.init()
384
screen = pygame.display.set_mode((800, 600))
385
386
# Create font with different styles
387
font = pygame.font.SysFont('arial', 32)
388
389
# Test text
390
test_text = "Styled Text Example"
391
392
# Get text dimensions
393
text_width, text_height = font.size(test_text)
394
print(f"Text dimensions: {text_width} x {text_height}")
395
396
# Get font metrics
397
print(f"Font height: {font.get_height()}")
398
print(f"Font ascent: {font.get_ascent()}")
399
print(f"Font descent: {font.get_descent()}")
400
print(f"Line size: {font.get_linesize()}")
401
402
running = True
403
while running:
404
for event in pygame.event.get():
405
if event.type == pygame.QUIT:
406
running = False
407
408
screen.fill((255, 255, 255))
409
410
y_pos = 50
411
412
# Normal text
413
normal_text = font.render(test_text, True, (0, 0, 0))
414
screen.blit(normal_text, (50, y_pos))
415
y_pos += 50
416
417
# Bold text
418
font.set_bold(True)
419
bold_text = font.render(test_text, True, (0, 0, 0))
420
screen.blit(bold_text, (50, y_pos))
421
font.set_bold(False)
422
y_pos += 50
423
424
# Italic text
425
font.set_italic(True)
426
italic_text = font.render(test_text, True, (0, 0, 0))
427
screen.blit(italic_text, (50, y_pos))
428
font.set_italic(False)
429
y_pos += 50
430
431
# Underlined text
432
font.set_underline(True)
433
underline_text = font.render(test_text, True, (0, 0, 0))
434
screen.blit(underline_text, (50, y_pos))
435
font.set_underline(False)
436
y_pos += 50
437
438
# Strikethrough text
439
font.set_strikethrough(True)
440
strike_text = font.render(test_text, True, (0, 0, 0))
441
screen.blit(strike_text, (50, y_pos))
442
font.set_strikethrough(False)
443
444
pygame.display.flip()
445
446
pygame.quit()
447
```
448
449
### Dynamic Text Input and Display
450
451
```python
452
import pygame
453
454
pygame.init()
455
screen = pygame.display.set_mode((800, 600))
456
457
font = pygame.font.Font(None, 36)
458
input_font = pygame.font.Font(None, 28)
459
460
# Text input variables
461
input_text = ""
462
messages = []
463
464
running = True
465
clock = pygame.time.Clock()
466
467
while running:
468
for event in pygame.event.get():
469
if event.type == pygame.QUIT:
470
running = False
471
elif event.type == pygame.KEYDOWN:
472
if event.key == pygame.K_RETURN:
473
if input_text.strip():
474
messages.append(input_text)
475
if len(messages) > 15: # Keep only last 15 messages
476
messages = messages[-15:]
477
input_text = ""
478
elif event.key == pygame.K_BACKSPACE:
479
input_text = input_text[:-1]
480
elif event.type == pygame.TEXTINPUT:
481
input_text += event.text
482
483
screen.fill((240, 240, 240))
484
485
# Draw title
486
title = font.render("Type messages and press Enter:", True, (0, 0, 0))
487
screen.blit(title, (50, 20))
488
489
# Draw input box
490
input_box = pygame.Rect(50, 60, 700, 40)
491
pygame.draw.rect(screen, (255, 255, 255), input_box)
492
pygame.draw.rect(screen, (0, 0, 0), input_box, 2)
493
494
# Draw input text
495
if input_text:
496
input_surface = input_font.render(input_text, True, (0, 0, 0))
497
screen.blit(input_surface, (input_box.x + 5, input_box.y + 8))
498
499
# Draw cursor
500
if pygame.time.get_ticks() % 1000 < 500: # Blinking cursor
501
cursor_x = input_box.x + 5
502
if input_text:
503
cursor_x += input_font.size(input_text)[0]
504
pygame.draw.line(screen, (0, 0, 0), (cursor_x, input_box.y + 5), (cursor_x, input_box.y + 35))
505
506
# Draw message history
507
y_offset = 120
508
for i, message in enumerate(messages):
509
# Alternate colors for readability
510
color = (0, 0, 100) if i % 2 == 0 else (100, 0, 0)
511
msg_surface = input_font.render(f"{i+1}: {message}", True, color)
512
screen.blit(msg_surface, (50, y_offset))
513
y_offset += 30
514
515
pygame.display.flip()
516
clock.tick(60)
517
518
pygame.quit()
519
```
520
521
### Multi-line Text and Word Wrapping
522
523
```python
524
import pygame
525
526
def render_multiline_text(text, font, color, max_width):
527
"""Render text with automatic word wrapping."""
528
words = text.split(' ')
529
lines = []
530
current_line = ""
531
532
for word in words:
533
test_line = current_line + " " + word if current_line else word
534
test_width = font.size(test_line)[0]
535
536
if test_width <= max_width:
537
current_line = test_line
538
else:
539
if current_line:
540
lines.append(current_line)
541
current_line = word
542
543
if current_line:
544
lines.append(current_line)
545
546
surfaces = []
547
for line in lines:
548
surface = font.render(line, True, color)
549
surfaces.append(surface)
550
551
return surfaces
552
553
pygame.init()
554
screen = pygame.display.set_mode((800, 600))
555
font = pygame.font.Font(None, 24)
556
557
long_text = """This is a very long text that demonstrates how to render multiple lines of text with automatic word wrapping. The text will be split into multiple lines that fit within the specified width. This technique is useful for creating text boxes, dialog systems, and other UI elements that need to display longer pieces of text in a readable format."""
558
559
running = True
560
while running:
561
for event in pygame.event.get():
562
if event.type == pygame.QUIT:
563
running = False
564
565
screen.fill((255, 255, 255))
566
567
# Render multiline text
568
text_surfaces = render_multiline_text(long_text, font, (0, 0, 0), 700)
569
570
# Draw text lines
571
y_offset = 50
572
line_height = font.get_linesize()
573
574
for surface in text_surfaces:
575
screen.blit(surface, (50, y_offset))
576
y_offset += line_height
577
578
pygame.display.flip()
579
580
pygame.quit()
581
```
582
583
### System Font Browser
584
585
```python
586
import pygame
587
588
pygame.init()
589
screen = pygame.display.set_mode((800, 600))
590
591
# Get list of system fonts
592
system_fonts = pygame.font.get_fonts()
593
print(f"Found {len(system_fonts)} system fonts")
594
595
# Display fonts
596
font_size = 20
597
display_font = pygame.font.Font(None, 16)
598
sample_text = "Sample Text 123"
599
600
scroll_offset = 0
601
fonts_per_page = 25
602
603
running = True
604
clock = pygame.time.Clock()
605
606
while running:
607
for event in pygame.event.get():
608
if event.type == pygame.QUIT:
609
running = False
610
elif event.type == pygame.KEYDOWN:
611
if event.key == pygame.K_UP:
612
scroll_offset = max(0, scroll_offset - 1)
613
elif event.key == pygame.K_DOWN:
614
scroll_offset = min(len(system_fonts) - fonts_per_page, scroll_offset + 1)
615
616
screen.fill((255, 255, 255))
617
618
# Title
619
title = pygame.font.Font(None, 32).render("System Fonts (Use UP/DOWN to scroll)", True, (0, 0, 0))
620
screen.blit(title, (50, 20))
621
622
# Display fonts
623
y_offset = 70
624
for i in range(fonts_per_page):
625
font_index = scroll_offset + i
626
if font_index >= len(system_fonts):
627
break
628
629
font_name = system_fonts[font_index]
630
631
# Font name
632
name_surface = display_font.render(f"{font_index}: {font_name}", True, (0, 0, 0))
633
screen.blit(name_surface, (50, y_offset))
634
635
# Sample text in that font
636
try:
637
sample_font = pygame.font.SysFont(font_name, font_size)
638
sample_surface = sample_font.render(sample_text, True, (100, 100, 100))
639
screen.blit(sample_surface, (300, y_offset))
640
except:
641
error_surface = display_font.render("(Error loading font)", True, (255, 0, 0))
642
screen.blit(error_surface, (300, y_offset))
643
644
y_offset += 22
645
646
pygame.display.flip()
647
clock.tick(30)
648
649
pygame.quit()
650
```