Cross-platform library for developing multimedia applications and video games in Python built on top of SDL
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.
Initialize and manage the font rendering system.
def init() -> None:
"""Initialize font module."""
def quit() -> None:
"""Uninitialize font module."""
def get_init() -> bool:
"""
Check if font module is initialized.
Returns:
bool: True if font module is initialized
"""
def get_default_font() -> str:
"""
Get filename of default font.
Returns:
str: Path to default font file
"""Access and use system-installed fonts.
def get_fonts() -> list[str]:
"""
Get list of available system fonts.
Returns:
list[str]: List of font names available on system
"""
def match_font(name: str, bold: bool = False, italic: bool = False) -> str:
"""
Find system font file path by name.
Args:
name (str): Font name to search for
bold (bool): Whether to look for bold variant
italic (bool): Whether to look for italic variant
Returns:
str: Path to font file or None if not found
"""
def SysFont(name: str, size: int, bold: bool = False, italic: bool = False) -> pygame.font.Font:
"""
Create font from system font by name.
Args:
name (str): System font name
size (int): Font size in pixels
bold (bool): Use bold variant
italic (bool): Use italic variant
Returns:
pygame.font.Font: Font object
"""Main font object for rendering text with various styling options.
class Font:
def __init__(self, filename, size: int):
"""
Create font from file or use default font.
Args:
filename: Font file path or None for default font
size (int): Font size in pixels
"""
def render(self, text: str, antialias: bool, color, background = None) -> pygame.Surface:
"""
Render text to a surface.
Args:
text (str): Text to render
antialias (bool): Use antialiasing for smoother text
color: Text color
background: Background color (None for transparent)
Returns:
pygame.Surface: Surface containing rendered text
"""
def size(self, text: str) -> tuple[int, int]:
"""
Get dimensions of text if it were rendered.
Args:
text (str): Text to measure
Returns:
tuple[int, int]: (width, height) in pixels
"""
def get_height(self) -> int:
"""
Get height of font in pixels.
Returns:
int: Font height including line spacing
"""
def get_linesize(self) -> int:
"""
Get recommended line spacing.
Returns:
int: Pixels between lines
"""
def get_ascent(self) -> int:
"""
Get font ascent (height above baseline).
Returns:
int: Pixels above baseline
"""
def get_descent(self) -> int:
"""
Get font descent (height below baseline).
Returns:
int: Pixels below baseline
"""
def metrics(self, text: str) -> list:
"""
Get metrics for each character in text.
Args:
text (str): Text to analyze
Returns:
list: List of (min_x, max_x, min_y, max_y, advance) for each character
"""
def get_bold(self) -> bool:
"""
Check if font is bold.
Returns:
bool: True if font is bold
"""
def set_bold(self, bold: bool) -> None:
"""
Set font bold style.
Args:
bold (bool): True for bold text
"""
def get_italic(self) -> bool:
"""
Check if font is italic.
Returns:
bool: True if font is italic
"""
def set_italic(self, italic: bool) -> None:
"""
Set font italic style.
Args:
italic (bool): True for italic text
"""
def get_underline(self) -> bool:
"""
Check if font is underlined.
Returns:
bool: True if font is underlined
"""
def set_underline(self, underline: bool) -> None:
"""
Set font underline style.
Args:
underline (bool): True for underlined text
"""
def get_strikethrough(self) -> bool:
"""
Check if font has strikethrough.
Returns:
bool: True if font has strikethrough
"""
def set_strikethrough(self, strikethrough: bool) -> None:
"""
Set font strikethrough style.
Args:
strikethrough (bool): True for strikethrough text
"""Enhanced font rendering with advanced typography features (available when pygame built with FreeType).
# pygame.freetype module (if available)
def init(cache_size: int = 64, resolution: int = 72) -> None:
"""
Initialize FreeType font system.
Args:
cache_size (int): Number of fonts to cache
resolution (int): DPI resolution
"""
def quit() -> None:
"""Uninitialize FreeType system."""
def get_init() -> bool:
"""
Check if FreeType is initialized.
Returns:
bool: True if initialized
"""
class Font:
def __init__(self, file, size: int = 0, font_index: int = 0, resolution: int = 0, ucs4: bool = False):
"""
Create FreeType font object.
Args:
file: Font file path or file object
size (int): Font size (0 for scalable)
font_index (int): Font index in collection
resolution (int): DPI resolution
ucs4 (bool): Enable UCS-4 character encoding
"""
def render(self, text: str, fgcolor = None, bgcolor = None, style: int = 0, rotation: int = 0, size: int = 0) -> tuple[pygame.Surface, pygame.Rect]:
"""
Render text with advanced options.
Args:
text (str): Text to render
fgcolor: Foreground color
bgcolor: Background color
style (int): Style flags (STYLE_BOLD, etc.)
rotation (int): Rotation angle in degrees
size (int): Font size override
Returns:
tuple[pygame.Surface, pygame.Rect]: Rendered surface and text rectangle
"""
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:
"""
Render text directly to a surface.
Args:
surf (pygame.Surface): Destination surface
dest: Position to render at
text (str): Text to render
(other args same as render())
Returns:
pygame.Rect: Rectangle where text was rendered
"""
def get_rect(self, text: str, style: int = 0, rotation: int = 0, size: int = 0) -> pygame.Rect:
"""
Get rectangle that would contain rendered text.
Args:
text (str): Text to measure
style (int): Style flags
rotation (int): Rotation angle
size (int): Font size
Returns:
pygame.Rect: Bounding rectangle
"""
def get_metrics(self, text: str, size: int = 0) -> list:
"""
Get detailed character metrics.
Args:
text (str): Text to analyze
size (int): Font size
Returns:
list: Character metric data
"""# Style flags for FreeType fonts
STYLE_NORMAL: int
STYLE_UNDERLINE: int
STYLE_OBLIQUE: int
STYLE_STRONG: int
STYLE_WIDE: int
STYLE_DEFAULT: intimport pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Create font objects
default_font = pygame.font.Font(None, 36) # Default font
system_font = pygame.font.SysFont('arial', 24) # System font
# Try to load custom font
try:
custom_font = pygame.font.Font('custom_font.ttf', 48)
except:
custom_font = default_font
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
# Render different text samples
text1 = default_font.render("Default Font", True, (0, 0, 0))
screen.blit(text1, (50, 50))
text2 = system_font.render("System Arial Font", True, (255, 0, 0))
screen.blit(text2, (50, 100))
text3 = custom_font.render("Custom Font", True, (0, 0, 255))
screen.blit(text3, (50, 150))
# Text with background
text4 = default_font.render("Text with Background", True, (255, 255, 255), (0, 128, 0))
screen.blit(text4, (50, 200))
pygame.display.flip()
pygame.quit()import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Create font with different styles
font = pygame.font.SysFont('arial', 32)
# Test text
test_text = "Styled Text Example"
# Get text dimensions
text_width, text_height = font.size(test_text)
print(f"Text dimensions: {text_width} x {text_height}")
# Get font metrics
print(f"Font height: {font.get_height()}")
print(f"Font ascent: {font.get_ascent()}")
print(f"Font descent: {font.get_descent()}")
print(f"Line size: {font.get_linesize()}")
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
y_pos = 50
# Normal text
normal_text = font.render(test_text, True, (0, 0, 0))
screen.blit(normal_text, (50, y_pos))
y_pos += 50
# Bold text
font.set_bold(True)
bold_text = font.render(test_text, True, (0, 0, 0))
screen.blit(bold_text, (50, y_pos))
font.set_bold(False)
y_pos += 50
# Italic text
font.set_italic(True)
italic_text = font.render(test_text, True, (0, 0, 0))
screen.blit(italic_text, (50, y_pos))
font.set_italic(False)
y_pos += 50
# Underlined text
font.set_underline(True)
underline_text = font.render(test_text, True, (0, 0, 0))
screen.blit(underline_text, (50, y_pos))
font.set_underline(False)
y_pos += 50
# Strikethrough text
font.set_strikethrough(True)
strike_text = font.render(test_text, True, (0, 0, 0))
screen.blit(strike_text, (50, y_pos))
font.set_strikethrough(False)
pygame.display.flip()
pygame.quit()import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
font = pygame.font.Font(None, 36)
input_font = pygame.font.Font(None, 28)
# Text input variables
input_text = ""
messages = []
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_RETURN:
if input_text.strip():
messages.append(input_text)
if len(messages) > 15: # Keep only last 15 messages
messages = messages[-15:]
input_text = ""
elif event.key == pygame.K_BACKSPACE:
input_text = input_text[:-1]
elif event.type == pygame.TEXTINPUT:
input_text += event.text
screen.fill((240, 240, 240))
# Draw title
title = font.render("Type messages and press Enter:", True, (0, 0, 0))
screen.blit(title, (50, 20))
# Draw input box
input_box = pygame.Rect(50, 60, 700, 40)
pygame.draw.rect(screen, (255, 255, 255), input_box)
pygame.draw.rect(screen, (0, 0, 0), input_box, 2)
# Draw input text
if input_text:
input_surface = input_font.render(input_text, True, (0, 0, 0))
screen.blit(input_surface, (input_box.x + 5, input_box.y + 8))
# Draw cursor
if pygame.time.get_ticks() % 1000 < 500: # Blinking cursor
cursor_x = input_box.x + 5
if input_text:
cursor_x += input_font.size(input_text)[0]
pygame.draw.line(screen, (0, 0, 0), (cursor_x, input_box.y + 5), (cursor_x, input_box.y + 35))
# Draw message history
y_offset = 120
for i, message in enumerate(messages):
# Alternate colors for readability
color = (0, 0, 100) if i % 2 == 0 else (100, 0, 0)
msg_surface = input_font.render(f"{i+1}: {message}", True, color)
screen.blit(msg_surface, (50, y_offset))
y_offset += 30
pygame.display.flip()
clock.tick(60)
pygame.quit()import pygame
def render_multiline_text(text, font, color, max_width):
"""Render text with automatic word wrapping."""
words = text.split(' ')
lines = []
current_line = ""
for word in words:
test_line = current_line + " " + word if current_line else word
test_width = font.size(test_line)[0]
if test_width <= max_width:
current_line = test_line
else:
if current_line:
lines.append(current_line)
current_line = word
if current_line:
lines.append(current_line)
surfaces = []
for line in lines:
surface = font.render(line, True, color)
surfaces.append(surface)
return surfaces
pygame.init()
screen = pygame.display.set_mode((800, 600))
font = pygame.font.Font(None, 24)
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."""
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
screen.fill((255, 255, 255))
# Render multiline text
text_surfaces = render_multiline_text(long_text, font, (0, 0, 0), 700)
# Draw text lines
y_offset = 50
line_height = font.get_linesize()
for surface in text_surfaces:
screen.blit(surface, (50, y_offset))
y_offset += line_height
pygame.display.flip()
pygame.quit()import pygame
pygame.init()
screen = pygame.display.set_mode((800, 600))
# Get list of system fonts
system_fonts = pygame.font.get_fonts()
print(f"Found {len(system_fonts)} system fonts")
# Display fonts
font_size = 20
display_font = pygame.font.Font(None, 16)
sample_text = "Sample Text 123"
scroll_offset = 0
fonts_per_page = 25
running = True
clock = pygame.time.Clock()
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
scroll_offset = max(0, scroll_offset - 1)
elif event.key == pygame.K_DOWN:
scroll_offset = min(len(system_fonts) - fonts_per_page, scroll_offset + 1)
screen.fill((255, 255, 255))
# Title
title = pygame.font.Font(None, 32).render("System Fonts (Use UP/DOWN to scroll)", True, (0, 0, 0))
screen.blit(title, (50, 20))
# Display fonts
y_offset = 70
for i in range(fonts_per_page):
font_index = scroll_offset + i
if font_index >= len(system_fonts):
break
font_name = system_fonts[font_index]
# Font name
name_surface = display_font.render(f"{font_index}: {font_name}", True, (0, 0, 0))
screen.blit(name_surface, (50, y_offset))
# Sample text in that font
try:
sample_font = pygame.font.SysFont(font_name, font_size)
sample_surface = sample_font.render(sample_text, True, (100, 100, 100))
screen.blit(sample_surface, (300, y_offset))
except:
error_surface = display_font.render("(Error loading font)", True, (255, 0, 0))
screen.blit(error_surface, (300, y_offset))
y_offset += 22
pygame.display.flip()
clock.tick(30)
pygame.quit()