PHPackages                             ls-a/font-finder - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. ls-a/font-finder

ActiveLibrary[File &amp; Storage](/categories/file-storage)

ls-a/font-finder
================

Find every font registered on server Operating System. Inspiration found in Apache FOP FontFileFinder

1.0.0(3d ago)00MITPHPPHP ^8.0CI passing

Since Feb 26Pushed 3d agoCompare

[ Source](https://github.com/ls-a-fr/font-finder-php)[ Packagist](https://packagist.org/packages/ls-a/font-finder)[ RSS](/packages/ls-a-font-finder/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (7)Versions (19)Used By (0)

Font Finder
===========

[](#font-finder)

[![Build Woff2 Decompress utility](https://github.com/ls-a-fr/php-font-finder/actions/workflows/woff2.yml/badge.svg)](https://github.com/ls-a-fr/php-font-finder/actions/workflows/woff2.yml)[![Test and bench](https://github.com/ls-a-fr/php-font-finder/actions/workflows/test-and-bench.yml/badge.svg)](https://github.com/ls-a-fr/php-font-finder/actions/workflows/test-and-bench.yml)

This documentation is also available in these languages:

- [Français](docs/LISEZMOI.md)

This library is an universal font finder: with *almost every* operating system, containing *almost every* font format, returns an array of standardized information. It aims to be (very) quick and retrieves minimal but sufficient information on fonts.

If you like this package and want to show you support, star this project: it means a lot to us!

Quick example
-------------

[](#quick-example)

```
$fonts = FontFileFinder::init()
    // Load system fonts (OS-dependent)
    ->addSystemFonts()
    // Load some directory
    ->addDirectoryRecursive(implode(DIRECTORY_SEPARATOR, [__DIR__, '..', 'tests', 'samples']))
    ->get();
```

In previous example, `$fonts` is an array of `Font` objects, aggregated by font name, with these properties:

- `filename`: where the font lies
- `name`: family name
- `bold`: bold flag (boolean)
- `italic`: italic flag (boolean)
- `weight`: CSS style weight, from 100 to 900

Find more in [documentation below](#documentation).

Installation
------------

[](#installation)

This library is available on Composer. Install it with:

```
composer require ls-a/font-finder
```

Operating system support
------------------------

[](#operating-system-support)

This library is currently tested on:

- Windows x64
- Windows i386
- Windows ARM
- macOS amd64
- macOS arm64
- Linux amd64
- Linux arm64
- Linux armv7
- FreeBSD amd64
- FreeBSD arm64
- OpenBSD amd64
- OpenBSD arm64
- Solaris amd64

For more information, feel free to check [test-and-bench action](.github/workflows/test-and-bench.yml).

Font format support
-------------------

[](#font-format-support)

This library currently retrieves font information in these formats:

- AdobeFontMetrics (\*.afm, in conjuction with PFA/PFB/T1/PS)
- BitstreamSpeedo (\*.spd)
- BsdVgaFont (\*.fnt, but BSD ones, not Microsoft)
- CompactFontFormat (\*.cff, both PostScript and binary)
- DataForkTrueTypeFont (\*.dfont)
- EmbeddedOpenType (\*.eot)
- GlyphBitmapDistributionFormat (\*.bdf)
- JimHersheyFont (\*.jhf)
- OpenTypeBitmap (\*.otb)
- OpenTypeCollection (\*.otc)
- OpenTypeFont (\*.otf)
- PcScreenFont (\*.psf)
- PcScreenFontUnicodeCompressed (\*.psfu.gz, usually found with \*.psf.fz extension)
- PcScreenFontCompressed (\*.psf.gz)
- PcScreenFontUnicode (\*.psfu)
- PortableCompiledFormat (\*.pcf)
- PortableCompiledFormatCompressed (\*.pcf.gz)
- PostScript (\*.ps)
- PrinterFontAscii (\*.pfa)
- PrinterFontBinary (\*.pfb)
- PrinterFontMetrics (\*.pfm, in conjuction with PFA/PFB/T1/PS)
- ScalableVectorGraphics (\*.svg)
- ScalableVectorGraphicsCompressed (\*.svgz)
- Type1 (\*.t1)
- TrueTypeCollection (\*.ttc)
- TrueTypeFont (\*.ttf)
- WebOpenFontFormat (\*.woff)
- WebOpenFontFormat2 (\*.woff2)
- WindowsBitmapFontCollection (\*.fon)

Why?
----

[](#why)

A rabbit hole, really. We needed to check some configuration option for our next package about XSL-FO, especially the `` option in Apache FOP configuration file. This option allows to retrieve all fonts registered in current OS.

First, we wanted to validate some values against this option. Then, we found old fonts on some operating systems does not publicize their name in the filename. And after some search on Composer, it seems no package does that. [Phenx PHP Font Lib](https://packagist.org/packages/phenx/php-font-lib) handles TrueType, OpenType and WOFF but that's all. And it is very slow with hundreds of fonts.

After some time and digging through history of fonts, this package became more and more a tribute to evolution of fonts. And it's a pleasure to discover so many ways to embed characters and typography.

If you can read French or can use a translator, find more about how we did it [here](docs/DEROULEMENT.md).
If you wish to browse through samples collection used in this package, see their provenance and our thanks, you may go [here](samples/README.md).

Performance
-----------

[](#performance)

Performance is checked with GitHub runners, in [test-and-bench action](.github/workflows/test-and-bench.yml).
Data displayed below are extracted from a single run, with following architectures:

- Windows: Windows amd64
- MacOS: MacOS amd64
- Linux: Linux amd64
- FreeBSD: Virtual machine amd64 inside Linux container
- OpenBSD: Virtual machine amd64 inside Linux container
- Solaris: Virtual machine amd64 inside Linux container

**Note:** Obviously, you should get better results in \*BSD and Solaris with bare metal environment.

Time displayed is meant to be *per file*: it's an average of every font available in samples + current operating system.

FiletypeWindowsMacLinuxFreeBSDOpenBSDSolarisbdf3ms48µs85µs81µs104µs81µscff37µs17µs103µs32µs39µs19µscff (ps)2ms621µs9ms1ms2ms1msdfont129µs49µs405µs114µs141µs91µseot123µs46µs401µs96µs118µs79µsfnt (BSD)5µs2µs7µs3µs4µs3µsfon (win)19µs5µs27µs7µs10µs7µsjhf4µs2µs5µs2µs3µs2µspcf75µs31µs246µs57µs70µs50µspcf.gz80µs43µs230µs68µs80µs57µspfa60µs36µs41µs24µs75µs58µspfb122µs83µs96µs40µs88µs81µspsf4µs2µs5µs2µs3µs2µspsf.gz7µs5µs9µs6µs7µs6µspsfu3µs1µs5µs2µs3µs3µspsfu.gz9µs6µs11µs7µs8µs7µsspd4µs2µs7µs2µs3µs3µssvg12µs11µs13µs8µs10µs9µssvgz129µs132µs102µs117µs121µs105µsttc372µs287µs2ms483µs549µs397µsttf189µs145µs1ms272µs327µs214µswoff5ms3ms7ms5ms5ms5mswoff2210ms21ms22ms30ms70ms27msYou may check metrics in [the specific run used for these metrics](https://github.com/ls-a-fr/php-font-finder/actions/runs/23244358247/job/67568710047).

If you like PHPBench and would prefer PHPBench metrics because you also care about memory peak, here you go:

### Windows amd64

[](#windows-amd64)

benchmarksubjectsetrevsitsmem\_peakmoderstdevSamplesPerformanceTestbenchSamples10051.946mb7.184ms±0.61%SystemPerformanceTestbenchSystem10051.946mb5.251μs±3.50%### Linux amd64

[](#linux-amd64)

benchmarksubjectsetrevsitsmem\_peakmoderstdevSystemPerformanceTestbenchSystem10052.189mb5.843μs±1.82%SamplesPerformanceTestbenchSamples10052.189mb1.645ms±0.29%### MacOS amd64

[](#macos-amd64)

benchmarksubjectsetrevsitsmem\_peakmoderstdevSamplesPerformanceTestbenchSamples10051.950mb1.064ms±4.56%SystemPerformanceTestbenchSystem10051.950mb3.099μs±9.82%### FreeBSD amd64 (VM)

[](#freebsd-amd64-vm)

benchmarksubjectsetrevsitsmem\_peakmoderstdevSamplesPerformanceTestbenchSamples10051.955mb346.581μs±1.02%SystemPerformanceTestbenchSystem10051.955mb3.367μs±9.12%### OpenBSD amd64 (VM)

[](#openbsd-amd64-vm)

benchmarksubjectsetrevsitsmem\_peakmoderstdevSamplesPerformanceTestbenchSamples10051.943mb3.870ms±1.69%SystemPerformanceTestbenchSystem10051.943mb4.224μs±6.37%### Solaris amd64 (VM)

[](#solaris-amd64-vm)

benchmarksubjectsetrevsitsmem\_peakmoderstdevSamplesPerformanceTestbenchSamples10051.948mb1.463ms±1.63%SystemPerformanceTestbenchSystem10051.948mb3.821μs±3.65%Documentation
-------------

[](#documentation)

Every call to this library should be done on `FontFileFinder` class.

### Usage

[](#usage)

#### Create an instance: inst()

[](#create-an-instance-inst)

```
// Returns a FontFileFinder instance
$instance = FontFileFinder::inst();
```

No operation will be done until you call the `get()` method: it only creates an objet.

#### Include system fonts: addSystemFonts()

[](#include-system-fonts-addsystemfonts)

```
// Returns a FontFileFinder instance
$instance = FontFileFinder::inst()
    ->addSystemFonts();
```

Based on current operating system, will add system font directories.

#### Include a specific directory: addDirectory()

[](#include-a-specific-directory-adddirectory)

```
// Returns a FontFileFinder instance
$instance = FontFileFinder::inst()
    // Tip: use absolute path
    ->addDirectory(implode(DIRECTORY_SEPARATOR, [
        __DIR__,
        'samples'
    ]));
```

This method will add any file found in this directory. Note that it is not recursive.

#### Include a specific directory, recursively: addDirectoryRecursive()

[](#include-a-specific-directory-recursively-adddirectoryrecursive)

```
// Returns a FontFileFinder instance
$instance = FontFileFinder::inst()
    // Tip: use absolute path
    ->addDirectoryRecursive(implode(DIRECTORY_SEPARATOR, [
        __DIR__,
        'samples'
    ]));
```

This method will add any file found in this directory, recursively.

#### Exclude patterns: except()

[](#exclude-patterns-except)

```
$instance = FontFileFinder::inst()
    // Exclude .git* files
    ->except('/\.git.*$/')
    // You may use a list
    ->except([
        '/myfolder\/*/',
        '/\.php$/'
    ]) ;
```

Except method accepts regular expressions and is tested against an absolute path.
If you prefer to exclude based on strings, check exceptExact.

#### Exclude file names: exceptExact()

[](#exclude-file-names-exceptexact)

```
$instance = FontFileFinder::inst()
    // Exclude .gitignore files
    ->exceptExact('.gitignore')
    // You may use a list
    ->exceptExact([
        '.DS_Store',
        '.gitkeep'
    ]);
```

This method checks your strings against an absolute path **with `str_ends_with`**, meaning you can exclude extensions without relying on regular expressions.

#### Get fonts

[](#get-fonts)

```
// Get fonts
$fonts = FontFileFinder::init()
    // Load system fonts (OS-dependent)
    ->addSystemFonts()
    // Load some directory
    ->addDirectoryRecursive(implode(DIRECTORY_SEPARATOR, [__DIR__, '..', 'tests', 'samples']))
    ->get();
```

You may want to retrieve other information, such as font count or errors. `get()` method allows to define what you want to get:

```
[$errors, $count, $fonts] = FontFileFinder::init()
    ->addSystemFonts()
    ->get('errors', 'count', 'fonts');
```

Currently, only `errors`, `count` and `fonts` are defined. You may define them in any order:

```
[$count, $errors] = FontFileFinder::init()
    ->addSystemFonts()
    ->get('count', 'errors');
```

### Configuration

[](#configuration)

#### Silence errors

[](#silence-errors)

You may want to silence errors: by default, errors are printed to standard error output (stderr).

```
$instance = FontFileFinder::inst()
    ->silent();
```

#### Enable performance metrics

[](#enable-performance-metrics)

Because sometimes, you wish to see performance metrics.

```
$instance = FontFileFinder::inst()
    ->enableMetrics();
```

You can disable them later with `disableMetrics`.

### Advanced

[](#advanced)

#### Use a configuration array

[](#use-a-configuration-array)

```
$fonts = FontFileFinder::load([
     'directories' => [
         [
             'recursive' => true,
             'path' => '/usr/local/...'
         ],
         '/home/user/...'
     ]
]);
```

Method `load` accepts `autoDetect` (boolean) or `directories`. It is not possible to get errors and count this way, but maybe in a next release!

#### Check system fonts

[](#check-system-fonts)

If you want a quick peek on system fonts, simply write:

```
$fonts = FontFileFinder::getSystemFonts();
```

You won't have access to any of FontFileFinder configuration, but sometimes it's just what you want.

#### Override FontDecoder

[](#override-fontdecoder)

FontFileFinder relies on a class called `FontDecoder`, which:

- Run through all decoders to find a match for the current file
- Actually does the performance check

If this class is not sufficient for your needs, you may define another subclass (that you have to write) and declare it this way:

```
$instance = FontFileFinder::inst()
    ->setDecoderClass(MyAwesomeClass::class);
```

Changelog
---------

[](#changelog)

Please refer to the [CHANGELOG](CHANGELOG.md) file to see the latest changes.

Support
-------

[](#support)

We put our heart into delivering high-quality products that are accessible to everyone. If you like our work, don’t hesitate to reach out to us for your next project!

Contributing
------------

[](#contributing)

Contributions are governed by the [CONTRIBUTING](https://github.com/ls-a-fr/.github/CONTRIBUTING.md) file.

Security
--------

[](#security)

If you’ve found a bug or vulnerability, please contact us by email at  instead of opening an issue, in order to protect the security of other users.

Credits
-------

[](#credits)

- Renaud Berthier

License
-------

[](#license)

The MIT License (MIT). Please see License File for more information.

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance99

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

18

Last Release

3d ago

Major Versions

0.18.0 → 1.0.02026-03-18

PHP version history (2 changes)0.1.0PHP ^8.0.0

0.18.0PHP ^8.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/190fe5341e199139e5f0a048b4b10e5cd07355c6b55ecaf6ca7ba41b65e97852?d=identicon)[renaudberthier](/maintainers/renaudberthier)

---

Top Contributors

[![renaudberthier](https://avatars.githubusercontent.com/u/1874017?v=4)](https://github.com/renaudberthier "renaudberthier (177 commits)")

---

Tags

unixfinderlinuxwindowsfontMACosoperating system

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ls-a-font-finder/health.svg)

```
[![Health](https://phpackages.com/badges/ls-a-font-finder/health.svg)](https://phpackages.com/packages/ls-a-font-finder)
```

###  Alternatives

[jolicode/jolinotif

Send desktop notifications on Windows, Linux, MacOS.

1.4k11.3M37](/packages/jolicode-jolinotif)[yosymfony/resource-watcher

A simple resource watcher using Symfony Finder

718.1M22](/packages/yosymfony-resource-watcher)[jolicode/php-os-helper

Helpers to detect the OS of the machine where PHP is running.

192.7M3](/packages/jolicode-php-os-helper)[ergebnis/classy

Provides collectors for classy constructs (classes, enums, interfaces, and traits).

382.8M18](/packages/ergebnis-classy)[devium/processes

This package is used to get a list of running processes on Windows or Unix-like systems, even Darwin

2426.2k](/packages/devium-processes)[arthurhoaro/favicon

PHP Library used to discover favicon from given URL

33725.4k](/packages/arthurhoaro-favicon)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
