A comprehensive Python document processing library that renders structured documents to PDF with advanced typography and customizable styling
—
Comprehensive measurement system providing units, calculations, layout dimensions, and precise positioning for document elements. The dimension system enables exact control over spacing, sizing, and positioning with support for both absolute and relative measurements.
Core dimension class providing measurement values with units and calculation capabilities.
class Dimension:
"""
Measurement value with unit specification and calculation support.
Represents distances, sizes, and positions with associated units,
providing arithmetic operations and unit conversions for layout calculations.
Parameters:
- value: float or int, numeric measurement value
- unit: DimensionUnit, unit specification (PT, MM, CM, INCH, etc.)
"""
def __init__(self, value=0, unit=None): ...
@property
def value(self): ... # Numeric value
@property
def unit(self): ... # Unit specification
# Arithmetic operations
def __add__(self, other): ... # Addition with other dimensions
def __sub__(self, other): ... # Subtraction with other dimensions
def __mul__(self, scalar): ... # Multiplication by scalar
def __rmul__(self, scalar): ... # Right multiplication by scalar
def __truediv__(self, scalar): ... # Division by scalar
def __neg__(self): ... # Negation
# Comparison operations
def __eq__(self, other): ... # Equality comparison
def __lt__(self, other): ... # Less than comparison
def __le__(self, other): ... # Less than or equal
def __gt__(self, other): ... # Greater than comparison
def __ge__(self, other): ... # Greater than or equal
# Conversion and calculation
def to_points(self, total_dimension=None): ... # Convert to points
def grow(self, value): ... # Increase by specified amount
# String representation
def __str__(self): ... # Human-readable string
def __repr__(self): ... # Developer representationPhysical measurement units with fixed relationships to real-world dimensions.
# Point unit (1/72 inch) - typography standard
PT = <DimensionUnit>
"""
Points - traditional typography unit.
1 point = 1/72 inch = 0.3528 mm
Most common unit for font sizes and fine measurements.
"""
# Pica unit (12 points) - typography standard
PICA = <DimensionUnit>
"""
Picas - typography unit for line measures.
1 pica = 12 points = 1/6 inch = 4.233 mm
Used for column widths and larger typography measurements.
"""
# Imperial units
INCH = <DimensionUnit>
"""
Inches - imperial measurement unit.
1 inch = 72 points = 6 picas = 25.4 mm
Standard for paper sizes and margins in US documents.
"""
# Metric units
MM = <DimensionUnit>
"""
Millimeters - metric unit.
1 mm = 2.834 points ≈ 0.0394 inches
Precise metric measurements for international documents.
"""
CM = <DimensionUnit>
"""
Centimeters - metric unit.
1 cm = 10 mm = 28.346 points ≈ 0.394 inches
Common for page dimensions and larger measurements.
"""Proportional measurement units that calculate values based on context or container dimensions.
PERCENT = <DimensionUnit>
"""
Percentage unit - relative to container or parent dimension.
Calculated as percentage of available space or reference dimension.
Example: 50*PERCENT = 50% of container width/height
"""
QUARTERS = <DimensionUnit>
"""
Quarter units - relative fractional measurements.
Divides available space into quarters for flexible layouts.
Example: 3*QUARTERS = 3/4 of available space
"""Functions and utilities for creating custom units and performing conversions between different measurement systems.
def create_unit(name, points_per_unit):
"""
Create custom dimension unit.
Parameters:
- name: str, unit name identifier
- points_per_unit: float, conversion factor to points
Returns:
- DimensionUnit for use in Dimension creation
"""
...
def convert_dimension(dimension, target_unit, reference_dimension=None):
"""
Convert dimension to different unit.
Parameters:
- dimension: Dimension, source dimension to convert
- target_unit: DimensionUnit, target unit for conversion
- reference_dimension: Dimension, reference for relative units
Returns:
- Dimension in target unit
"""
...
class DimensionUnit:
"""
Unit specification for dimension calculations.
Encapsulates unit properties including name, conversion factors,
and calculation methods for different unit types.
"""
def __init__(self, name, points_per_unit=None, relative=False): ...
@property
def name(self): ... # Unit name
@property
def is_relative(self): ... # Whether unit is relative
def to_points(self, value, reference=None): ... # Convert to pointsAdvanced calculation functions for common layout and spacing operations.
def max_dimension(*dimensions):
"""
Get maximum dimension from multiple dimensions.
Parameters:
- *dimensions: Dimension objects to compare
Returns:
- Dimension with maximum value
"""
...
def min_dimension(*dimensions):
"""
Get minimum dimension from multiple dimensions.
Parameters:
- *dimensions: Dimension objects to compare
Returns:
- Dimension with minimum value
"""
...
def sum_dimensions(*dimensions):
"""
Sum multiple dimensions.
Parameters:
- *dimensions: Dimension objects to sum
Returns:
- Dimension with total value
"""
...
def distribute_space(total_space, *proportions):
"""
Distribute space proportionally.
Parameters:
- total_space: Dimension, total space to distribute
- *proportions: float values for proportional distribution
Returns:
- list of Dimension objects with distributed space
"""
...Specialized classes and functions for managing spacing, margins, and layout calculations.
class Spacing:
"""
Spacing configuration for margins, padding, and gaps.
Manages spacing around elements with support for different
values for top, right, bottom, and left sides.
Parameters:
- top: Dimension, top spacing
- right: Dimension, right spacing (defaults to top)
- bottom: Dimension, bottom spacing (defaults to top)
- left: Dimension, left spacing (defaults to right)
"""
def __init__(self, top, right=None, bottom=None, left=None): ...
@property
def top(self): ... # Top spacing
@property
def right(self): ... # Right spacing
@property
def bottom(self): ... # Bottom spacing
@property
def left(self): ... # Left spacing
@property
def horizontal(self): ... # Total horizontal spacing (left + right)
@property
def vertical(self): ... # Total vertical spacing (top + bottom)
class Margins(Spacing):
"""Margin specification for page and element margins."""
class Padding(Spacing):
"""Padding specification for interior element spacing."""
def calculate_available_space(container_size, margins, padding=None):
"""
Calculate available content space within container.
Parameters:
- container_size: Dimension, total container size
- margins: Margins, margin specification
- padding: Padding, optional padding specification
Returns:
- Dimension with available content space
"""
...Predefined paper sizes and page dimension calculations for document layout.
def get_paper_dimensions(paper_name, orientation='portrait'):
"""
Get dimensions for standard paper size.
Parameters:
- paper_name: str, paper size name ('A4', 'LETTER', etc.)
- orientation: str, 'portrait' or 'landscape'
Returns:
- (width, height) tuple of Dimension objects
"""
...
def calculate_content_area(paper_size, margins):
"""
Calculate content area within page margins.
Parameters:
- paper_size: (width, height) tuple of page dimensions
- margins: Margins, page margin specification
Returns:
- (width, height) tuple of content area dimensions
"""
...
# Common paper size calculations
A4_WIDTH = 210*MM # A4 paper width
A4_HEIGHT = 297*MM # A4 paper height
LETTER_WIDTH = 8.5*INCH # US Letter width
LETTER_HEIGHT = 11*INCH # US Letter heightfrom rinohtype.dimension import Dimension, PT, MM, CM, INCH
# Create dimensions with different units
font_size = 12*PT
margin = 25*MM
width = 6*INCH
height = 4*CM
# Arithmetic operations
total_height = height + 2*margin
scaled_width = width * 1.5
half_margin = margin / 2
# Comparison operations
if font_size > 10*PT:
print("Large font")
# Convert between units
margin_in_points = margin.to_points()
width_in_mm = width.to_points() * MM.to_points(1) # Approximate conversionfrom rinohtype.dimension import convert_dimension
# Convert measurements between units
page_width_mm = 210*MM
page_width_inches = convert_dimension(page_width_mm, INCH)
page_width_points = convert_dimension(page_width_mm, PT)
print(f"A4 width: {page_width_mm} = {page_width_inches} = {page_width_points}")
# Working with different units in calculations
left_margin = 1*INCH
right_margin = 25*MM
total_horizontal_margin = left_margin + right_margin # Automatic unit handlingfrom rinohtype.dimension import PERCENT, QUARTERS
# Percentage-based dimensions
half_width = 50*PERCENT # 50% of container width
three_quarters = 75*PERCENT # 75% of container
# Quarter-based fractional dimensions
one_quarter = 1*QUARTERS # 1/4 of container
three_quarters_alt = 3*QUARTERS # 3/4 of container
# Calculate relative dimensions with reference
container_width = 200*MM
actual_half_width = half_width.to_points(container_width)from rinohtype.dimension import Spacing, Margins, Padding
# Uniform spacing
uniform_margin = Margins(25*MM) # 25mm on all sides
# Different spacing per side
custom_margins = Margins(
top=30*MM,
right=20*MM,
bottom=25*MM,
left=20*MM
)
# Shorthand for horizontal/vertical
page_margins = Margins(25*MM, 20*MM) # 25mm top/bottom, 20mm left/right
# Element padding
element_padding = Padding(
top=6*PT,
right=12*PT,
bottom=6*PT,
left=12*PT
)
# Calculate total spacing
total_horizontal = custom_margins.horizontal # left + right
total_vertical = custom_margins.vertical # top + bottomfrom rinohtype.dimension import calculate_available_space, distribute_space
# Calculate available content space
page_size = (210*MM, 297*MM) # A4 dimensions
page_margins = Margins(25*MM)
content_area = calculate_available_space(page_size[0], page_margins)
print(f"Content width: {content_area}") # 210mm - 50mm = 160mm
# Distribute space proportionally
total_width = 200*MM
column_widths = distribute_space(total_width, 2, 1, 2) # 2:1:2 ratio
# Result: [80mm, 40mm, 80mm]
# Multi-column layout calculation
available_width = 160*MM
gutter_width = 5*MM
num_columns = 3
total_gutter_width = gutter_width * (num_columns - 1)
column_width = (available_width - total_gutter_width) / num_columnsfrom rinohtype.dimension import max_dimension, min_dimension, sum_dimensions
# Find maximum dimension
widths = [120*MM, 4.5*INCH, 300*PT]
max_width = max_dimension(*widths)
# Find minimum dimension
heights = [150*MM, 6*INCH, 400*PT]
min_height = min_dimension(*heights)
# Sum dimensions
spacing_values = [6*PT, 3*MM, 0.1*INCH]
total_spacing = sum_dimensions(*spacing_values)
# Complex calculations for grid layouts
def calculate_grid_dimensions(container_width, columns, gutter):
"""Calculate grid column widths with gutters."""
total_gutter = gutter * (columns - 1)
available_width = container_width - total_gutter
column_width = available_width / columns
return {
'column_width': column_width,
'gutter_width': gutter,
'total_width': container_width
}
grid = calculate_grid_dimensions(200*MM, 4, 5*MM)from rinohtype.dimension import create_unit, DimensionUnit
# Create custom unit for specific use case
# Example: Creating a unit for a specific grid system
GRID_UNIT = create_unit('grid', 18) # 18 points per grid unit
# Use custom unit
element_width = 5*GRID_UNIT # 5 grid units = 90 points
element_height = 3*GRID_UNIT # 3 grid units = 54 points
# Custom typographic unit
# Cicero (European typography unit ≈ 1.063 picas)
CICERO = create_unit('cicero', 12.79) # Approximately 12.79 points
line_measure = 20*CICERO # 20 ciceros widedef setup_document_dimensions():
"""Calculate document layout dimensions."""
# Page setup
paper_width = 210*MM # A4 width
paper_height = 297*MM # A4 height
# Margins
top_margin = 25*MM
bottom_margin = 25*MM
left_margin = 20*MM
right_margin = 20*MM
# Calculate content area
content_width = paper_width - left_margin - right_margin
content_height = paper_height - top_margin - bottom_margin
# Typography settings
base_font_size = 11*PT
line_height = base_font_size * 1.2
# Calculate lines per page
lines_per_page = int(content_height.to_points() / line_height.to_points())
return {
'page_size': (paper_width, paper_height),
'content_area': (content_width, content_height),
'margins': Margins(top_margin, right_margin, bottom_margin, left_margin),
'typography': {
'font_size': base_font_size,
'line_height': line_height,
'lines_per_page': lines_per_page
}
}
layout = setup_document_dimensions()def responsive_dimension(base_dimension, scale_factors):
"""Create responsive dimensions for different contexts."""
return {
'small': base_dimension * scale_factors.get('small', 0.8),
'medium': base_dimension * scale_factors.get('medium', 1.0),
'large': base_dimension * scale_factors.get('large', 1.2)
}
# Responsive font sizes
base_size = 11*PT
heading_sizes = responsive_dimension(base_size, {
'small': 1.2,
'medium': 1.5,
'large': 2.0
})
# Responsive margins
base_margin = 20*MM
responsive_margins = responsive_dimension(base_margin, {
'small': 0.75,
'medium': 1.0,
'large': 1.25
})def validate_dimension(dimension, min_value=None, max_value=None):
"""Validate dimension within acceptable range."""
if min_value and dimension < min_value:
raise ValueError(f"Dimension {dimension} below minimum {min_value}")
if max_value and dimension > max_value:
raise ValueError(f"Dimension {dimension} exceeds maximum {max_value}")
return True
def safe_dimension_operation(op, *dimensions):
"""Perform dimension operation with error handling."""
try:
return op(*dimensions)
except (TypeError, ValueError) as e:
print(f"Dimension operation error: {e}")
return None
# Usage
try:
validate_dimension(font_size, min_value=6*PT, max_value=72*PT)
result = safe_dimension_operation(sum_dimensions, 10*PT, 5*MM, 0.1*INCH)
except ValueError as e:
print(f"Validation error: {e}")Install with Tessl CLI
npx tessl i tessl/pypi-rinohtype