or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-font-operations.mddrawing-pens.mdfont-building.mdfont-processing.mdindex.mdutilities-tools.mdvariable-fonts.md

utilities-tools.mddocs/

0

# Utilities and Tools

1

2

Miscellaneous utilities for text processing, geometric transformations, XML handling, and various font-related calculations. These utilities provide foundational support for font manipulation and processing workflows.

3

4

## Capabilities

5

6

### Geometric Transformations

7

8

2D affine transformation matrix operations for scaling, rotation, translation, and skewing.

9

10

```python { .api }

11

class Transform:

12

def __init__(self, a=1, b=0, c=0, d=1, e=0, f=0):

13

"""

14

Create 2D affine transformation matrix.

15

16

Parameters:

17

- a, b, c, d, e, f: float, transformation matrix components

18

[a c e] [x] [a*x + c*y + e]

19

[b d f] × [y] = [b*x + d*y + f]

20

[0 0 1] [1] [1]

21

"""

22

23

def transformPoint(self, point):

24

"""

25

Apply transformation to point.

26

27

Parameters:

28

- point: Tuple[float, float], input coordinates

29

30

Returns:

31

Tuple[float, float]: Transformed coordinates

32

"""

33

34

def transformPoints(self, points):

35

"""

36

Apply transformation to list of points.

37

38

Parameters:

39

- points: List[Tuple[float, float]], input points

40

41

Returns:

42

List[Tuple[float, float]]: Transformed points

43

"""

44

45

def scale(self, x, y=None):

46

"""

47

Create scaling transformation.

48

49

Parameters:

50

- x: float, horizontal scale factor

51

- y: float, vertical scale factor (default: same as x)

52

53

Returns:

54

Transform: New scaling transformation

55

"""

56

57

def rotate(self, angle):

58

"""

59

Create rotation transformation.

60

61

Parameters:

62

- angle: float, rotation angle in radians

63

64

Returns:

65

Transform: New rotation transformation

66

"""

67

68

def translate(self, x, y):

69

"""

70

Create translation transformation.

71

72

Parameters:

73

- x, y: float, translation offsets

74

75

Returns:

76

Transform: New translation transformation

77

"""

78

79

def skew(self, x, y):

80

"""

81

Create skew transformation.

82

83

Parameters:

84

- x, y: float, skew angles in radians

85

86

Returns:

87

Transform: New skew transformation

88

"""

89

90

def inverse(self):

91

"""

92

Get inverse transformation.

93

94

Returns:

95

Transform: Inverse transformation matrix

96

"""

97

98

def __mul__(self, other):

99

"""

100

Multiply transformations.

101

102

Parameters:

103

- other: Transform, transformation to multiply with

104

105

Returns:

106

Transform: Combined transformation

107

"""

108

109

Identity = Transform() # Identity transformation constant

110

```

111

112

#### Transformation Examples

113

114

```python

115

from fontTools.misc.transform import Transform, Identity

116

import math

117

118

# Create basic transformations

119

scale_transform = Transform().scale(2.0, 1.5) # Scale 2x horizontally, 1.5x vertically

120

rotate_transform = Transform().rotate(math.radians(45)) # Rotate 45 degrees

121

translate_transform = Transform().translate(100, 50) # Move 100 right, 50 up

122

123

# Combine transformations

124

combined = scale_transform * rotate_transform * translate_transform

125

126

# Apply to points

127

original_points = [(0, 0), (100, 0), (100, 100), (0, 100)]

128

transformed_points = combined.transformPoints(original_points)

129

130

print("Original:", original_points)

131

print("Transformed:", transformed_points)

132

133

# Create complex transformation

134

complex_transform = (Transform()

135

.translate(-50, -50) # Center at origin

136

.rotate(math.radians(30)) # Rotate 30 degrees

137

.scale(1.2) # Scale up 20%

138

.translate(200, 300)) # Move to final position

139

140

# Apply to single point

141

x, y = complex_transform.transformPoint((100, 100))

142

print(f"Point (100, 100) transformed to ({x}, {y})")

143

```

144

145

### Array and Bounds Utilities

146

147

Functions for working with coordinate arrays and bounding box calculations.

148

149

```python { .api }

150

def calcBounds(array):

151

"""

152

Calculate bounding box of coordinate array.

153

154

Parameters:

155

- array: List[Tuple[float, float]], coordinate points

156

157

Returns:

158

Tuple[float, float, float, float]: (xMin, yMin, xMax, yMax) or None if empty

159

"""

160

161

def updateBounds(bounds, p):

162

"""

163

Update bounding box to include point.

164

165

Parameters:

166

- bounds: Tuple[float, float, float, float], current bounds (xMin, yMin, xMax, yMax)

167

- p: Tuple[float, float], point to include

168

169

Returns:

170

Tuple[float, float, float, float]: Updated bounds

171

"""

172

173

def pointInRect(p, rect):

174

"""

175

Test if point is inside rectangle.

176

177

Parameters:

178

- p: Tuple[float, float], point coordinates

179

- rect: Tuple[float, float, float, float], rectangle (xMin, yMin, xMax, yMax)

180

181

Returns:

182

bool: True if point is inside rectangle

183

"""

184

185

def rectCenter(rect):

186

"""

187

Get center point of rectangle.

188

189

Parameters:

190

- rect: Tuple[float, float, float, float], rectangle (xMin, yMin, xMax, yMax)

191

192

Returns:

193

Tuple[float, float]: Center coordinates

194

"""

195

196

def intRect(rect):

197

"""

198

Convert rectangle to integer coordinates.

199

200

Parameters:

201

- rect: Tuple[float, float, float, float], rectangle with float coordinates

202

203

Returns:

204

Tuple[int, int, int, int]: Rectangle with integer coordinates

205

"""

206

```

207

208

#### Array and Bounds Examples

209

210

```python

211

from fontTools.misc.arrayTools import calcBounds, updateBounds, rectCenter

212

213

# Calculate bounds of point array

214

points = [(10, 20), (50, 10), (30, 60), (80, 40)]

215

bounds = calcBounds(points)

216

print(f"Bounds: {bounds}") # (10, 10, 80, 60)

217

218

# Update bounds incrementally

219

current_bounds = None

220

for point in points:

221

if current_bounds is None:

222

current_bounds = (point[0], point[1], point[0], point[1])

223

else:

224

current_bounds = updateBounds(current_bounds, point)

225

226

print(f"Incremental bounds: {current_bounds}")

227

228

# Get rectangle center

229

center = rectCenter(bounds)

230

print(f"Center: {center}") # (45.0, 35.0)

231

```

232

233

### Text Processing Utilities

234

235

Functions for handling hexadecimal data, safe evaluation, and text conversion.

236

237

```python { .api }

238

def safeEval(data):

239

"""

240

Safely evaluate simple Python expressions.

241

242

Parameters:

243

- data: str, Python expression to evaluate

244

245

Returns:

246

Any: Evaluation result

247

"""

248

249

def readHex(content):

250

"""

251

Read hexadecimal string and return bytes.

252

253

Parameters:

254

- content: str, hexadecimal string

255

256

Returns:

257

bytes: Decoded binary data

258

"""

259

260

def writeHex(data):

261

"""

262

Convert bytes to hexadecimal string.

263

264

Parameters:

265

- data: bytes, binary data

266

267

Returns:

268

str: Hexadecimal representation

269

"""

270

271

def hexStr(value):

272

"""

273

Convert integer to hexadecimal string.

274

275

Parameters:

276

- value: int, integer value

277

278

Returns:

279

str: Hexadecimal string (e.g., "0x1a2b")

280

"""

281

```

282

283

#### Text Processing Examples

284

285

```python

286

from fontTools.misc.textTools import safeEval, readHex, writeHex, hexStr

287

288

# Safe evaluation

289

result = safeEval("2 + 3 * 4")

290

print(f"Safe eval result: {result}") # 14

291

292

# Hex conversion

293

hex_string = "48656c6c6f20576f726c64" # "Hello World" in hex

294

binary_data = readHex(hex_string)

295

print(f"Decoded: {binary_data}") # b'Hello World'

296

297

# Convert back to hex

298

hex_result = writeHex(binary_data)

299

print(f"Re-encoded: {hex_result}")

300

301

# Integer to hex

302

print(f"0x{255:02x}") # 0xff

303

print(hexStr(255)) # 0xff

304

```

305

306

### Rounding Utilities

307

308

Functions for various rounding operations commonly used in font processing.

309

310

```python { .api }

311

def roundFunc(value, func=round):

312

"""

313

Apply rounding function safely.

314

315

Parameters:

316

- value: float, value to round

317

- func: callable, rounding function (default: round)

318

319

Returns:

320

int: Rounded value

321

"""

322

323

def noRound(value):

324

"""

325

No-op rounding function (returns input unchanged).

326

327

Parameters:

328

- value: float, input value

329

330

Returns:

331

float: Unchanged input value

332

"""

333

334

def otRound(value):

335

"""

336

OpenType-style rounding (rounds 0.5 up).

337

338

Parameters:

339

- value: float, value to round

340

341

Returns:

342

int: Rounded value using OpenType rules

343

"""

344

```

345

346

#### Rounding Examples

347

348

```python

349

from fontTools.misc.roundTools import roundFunc, noRound, otRound

350

351

values = [1.2, 1.5, 1.7, 2.5, -1.5]

352

353

print("Standard rounding:")

354

for val in values:

355

print(f" {val} -> {roundFunc(val)}")

356

357

print("OpenType rounding:")

358

for val in values:

359

print(f" {val} -> {otRound(val)}")

360

361

print("No rounding:")

362

for val in values:

363

print(f" {val} -> {noRound(val)}")

364

```

365

366

### Fixed-Point Arithmetic

367

368

Utilities for working with fixed-point numbers used in font tables.

369

370

```python { .api }

371

def fixedToFloat(value, precisionBits=16):

372

"""

373

Convert fixed-point integer to floating-point.

374

375

Parameters:

376

- value: int, fixed-point value

377

- precisionBits: int, number of fractional bits (default: 16)

378

379

Returns:

380

float: Floating-point representation

381

"""

382

383

def floatToFixed(value, precisionBits=16):

384

"""

385

Convert floating-point to fixed-point integer.

386

387

Parameters:

388

- value: float, floating-point value

389

- precisionBits: int, number of fractional bits (default: 16)

390

391

Returns:

392

int: Fixed-point representation

393

"""

394

395

def ensureVersionIsLong(value):

396

"""

397

Ensure version number is in correct format.

398

399

Parameters:

400

- value: int or float, version number

401

402

Returns:

403

int: Properly formatted version number

404

"""

405

```

406

407

#### Fixed-Point Examples

408

409

```python

410

from fontTools.misc.fixedTools import fixedToFloat, floatToFixed

411

412

# Convert between fixed-point and float

413

float_val = 1.5

414

fixed_val = floatToFixed(float_val)

415

print(f"Float {float_val} -> Fixed {fixed_val}") # 98304 (1.5 * 65536)

416

417

back_to_float = fixedToFloat(fixed_val)

418

print(f"Fixed {fixed_val} -> Float {back_to_float}") # 1.5

419

420

# Different precision

421

fixed_8bit = floatToFixed(1.5, precisionBits=8)

422

print(f"8-bit fixed: {fixed_8bit}") # 384 (1.5 * 256)

423

```

424

425

### Bezier Curve Mathematics

426

427

Mathematical functions for working with Bezier curves and path calculations.

428

429

```python { .api }

430

def calcQuadraticBounds(pt1, pt2, pt3):

431

"""

432

Calculate bounding box of quadratic Bezier curve.

433

434

Parameters:

435

- pt1, pt2, pt3: Tuple[float, float], curve control points

436

437

Returns:

438

Tuple[float, float, float, float]: Bounding box (xMin, yMin, xMax, yMax)

439

"""

440

441

def calcCubicBounds(pt1, pt2, pt3, pt4):

442

"""

443

Calculate bounding box of cubic Bezier curve.

444

445

Parameters:

446

- pt1, pt2, pt3, pt4: Tuple[float, float], curve control points

447

448

Returns:

449

Tuple[float, float, float, float]: Bounding box (xMin, yMin, xMax, yMax)

450

"""

451

452

def splitLine(pt1, pt2, where):

453

"""

454

Split line segment at parameter t.

455

456

Parameters:

457

- pt1, pt2: Tuple[float, float], line endpoints

458

- where: float, parameter t (0.0 to 1.0)

459

460

Returns:

461

Tuple[Tuple, Tuple]: Two line segments

462

"""

463

464

def splitQuadratic(pt1, pt2, pt3, where):

465

"""

466

Split quadratic Bezier curve at parameter t.

467

468

Parameters:

469

- pt1, pt2, pt3: Tuple[float, float], curve control points

470

- where: float, parameter t (0.0 to 1.0)

471

472

Returns:

473

Tuple[Tuple, Tuple]: Two quadratic curve segments

474

"""

475

476

def splitCubic(pt1, pt2, pt3, pt4, where):

477

"""

478

Split cubic Bezier curve at parameter t.

479

480

Parameters:

481

- pt1, pt2, pt3, pt4: Tuple[float, float], curve control points

482

- where: float, parameter t (0.0 to 1.0)

483

484

Returns:

485

Tuple[Tuple, Tuple]: Two cubic curve segments

486

"""

487

```

488

489

#### Bezier Mathematics Examples

490

491

```python

492

from fontTools.misc.bezierTools import calcCubicBounds, splitCubic

493

494

# Calculate bounds of cubic curve

495

pt1 = (0, 0)

496

pt2 = (50, 100)

497

pt3 = (150, 100)

498

pt4 = (200, 0)

499

500

bounds = calcCubicBounds(pt1, pt2, pt3, pt4)

501

print(f"Curve bounds: {bounds}")

502

503

# Split curve at midpoint

504

left_curve, right_curve = splitCubic(pt1, pt2, pt3, pt4, 0.5)

505

print(f"Left curve: {left_curve}")

506

print(f"Right curve: {right_curve}")

507

```

508

509

### XML Processing

510

511

Utilities for reading and writing XML data in font processing contexts.

512

513

```python { .api }

514

class XMLWriter:

515

def __init__(self, outFile, encoding="utf-8"):

516

"""

517

XML output writer.

518

519

Parameters:

520

- outFile: file-like, output file object

521

- encoding: str, character encoding

522

"""

523

524

def begintag(self, tag, **kwargs):

525

"""

526

Write opening XML tag.

527

528

Parameters:

529

- tag: str, tag name

530

- kwargs: tag attributes

531

"""

532

533

def endtag(self, tag):

534

"""

535

Write closing XML tag.

536

537

Parameters:

538

- tag: str, tag name

539

"""

540

541

def simpletag(self, tag, **kwargs):

542

"""

543

Write self-closing XML tag.

544

545

Parameters:

546

- tag: str, tag name

547

- kwargs: tag attributes

548

"""

549

550

def data(self, data):

551

"""

552

Write XML character data.

553

554

Parameters:

555

- data: str, character data

556

"""

557

558

class XMLReader:

559

def __init__(self, inFile):

560

"""

561

XML input reader.

562

563

Parameters:

564

- inFile: file-like, input file object

565

"""

566

567

def read(self, handler):

568

"""

569

Parse XML with content handler.

570

571

Parameters:

572

- handler: object, content handler with start/end/data methods

573

"""

574

```

575

576

### Logging Configuration

577

578

Utilities for configuring FontTools logging output.

579

580

```python { .api }

581

def configLogger(level="INFO", format=None, logger=None):

582

"""

583

Configure FontTools logging.

584

585

Parameters:

586

- level: str, logging level ("DEBUG", "INFO", "WARNING", "ERROR")

587

- format: str, log message format string

588

- logger: Logger, specific logger to configure (default: fontTools logger)

589

"""

590

```

591

592

#### Logging Examples

593

594

```python

595

from fontTools.misc.loggingTools import configLogger

596

import logging

597

598

# Configure FontTools logging

599

configLogger(level="DEBUG")

600

601

# Use FontTools logger

602

from fontTools import log

603

log.info("Processing font file")

604

log.warning("Unusual glyph structure detected")

605

log.error("Font validation failed")

606

607

# Configure with custom format

608

configLogger(

609

level="INFO",

610

format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"

611

)

612

```

613

614

### File System Utilities

615

616

Cross-platform file system operations for font processing.

617

618

```python

619

from fontTools.misc.filesystem import open_file, ensure_path

620

621

# Platform-aware file opening

622

with open_file("font.ttf", "rb") as f:

623

font_data = f.read()

624

625

# Ensure directory exists

626

ensure_path("output/fonts/")

627

```

628

629

### Integration Examples

630

631

```python

632

def optimize_glyph_coordinates(glyph_coords, transform=None):

633

"""Example combining multiple utilities."""

634

from fontTools.misc.arrayTools import calcBounds

635

from fontTools.misc.roundTools import otRound

636

from fontTools.misc.transform import Transform

637

638

# Apply transformation if provided

639

if transform:

640

coords = transform.transformPoints(glyph_coords)

641

else:

642

coords = glyph_coords

643

644

# Round coordinates using OpenType rules

645

rounded_coords = [(otRound(x), otRound(y)) for x, y in coords]

646

647

# Calculate optimized bounds

648

bounds = calcBounds(rounded_coords)

649

650

return rounded_coords, bounds

651

652

def create_web_font_transform(target_upm=1000):

653

"""Create transformation for web font optimization."""

654

from fontTools.misc.transform import Transform

655

656

# Common web font optimizations

657

transform = Transform()

658

659

# Scale to target units per em

660

current_upm = 2048 # Assume source UPM

661

scale_factor = target_upm / current_upm

662

transform = transform.scale(scale_factor)

663

664

# Optional: slight compression for better rendering

665

transform = transform.scale(1.0, 0.95)

666

667

return transform

668

```