Skip to content

Commit

Permalink
Merge pull request #3830 from oleibman/issue2809
Browse files Browse the repository at this point in the history
Recurse Directories Searching for Font File
  • Loading branch information
oleibman authored Dec 18, 2023
2 parents 4e7a148 + 551d69c commit 6f84f41
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 4 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,12 @@ and this project adheres to [Semantic Versioning](https://semver.org).
- Html omitting some charts. [Issue #3767](https://github.com/PHPOffice/PhpSpreadsheet/issues/3767) [PR #3771](https://github.com/PHPOffice/PhpSpreadsheet/pull/3771)
- Case Insensitive Comparison for Sheet Names [PR #3791](https://github.com/PHPOffice/PhpSpreadsheet/pull/3791)
- Performance improvement for Xlsx Reader. [Issue #3683](https://github.com/PHPOffice/PhpSpreadsheet/issues/3683) [PR #3810](https://github.com/PHPOffice/PhpSpreadsheet/pull/3810)
- Strip `xlfn.` and `xlws.` from Formula Translations. [Issue #3819](https://github.com/PHPOffice/PhpSpreadsheet/issues/3819) [PR #3828](https://github.com/PHPOffice/PhpSpreadsheet/pull/3828)
- Prevent loop in Shared/File. [Issue #3807](https://github.com/PHPOffice/PhpSpreadsheet/issues/3807) [PR #3809](https://github.com/PHPOffice/PhpSpreadsheet/pull/3809)
- Consistent handling of decimal/thousands separators between StringHelper and Php setlocale. [Issue #3811](https://github.com/PHPOffice/PhpSpreadsheet/issues/3811) [PR #3815](https://github.com/PHPOffice/PhpSpreadsheet/pull/3815)
- Clone worksheet with tables or charts. [Issue #3820](https://github.com/PHPOffice/PhpSpreadsheet/issues/3820) [PR #3821](https://github.com/PHPOffice/PhpSpreadsheet/pull/3821)
- COUNTIFS Does Not Require xlfn. [Issue #3819](https://github.com/PHPOffice/PhpSpreadsheet/issues/3819) [PR #3827](https://github.com/PHPOffice/PhpSpreadsheet/pull/3827)
- Strip `xlfn.` and `xlws.` from Formula Translations. [Issue #3819](https://github.com/PHPOffice/PhpSpreadsheet/issues/3819) [PR #3828](https://github.com/PHPOffice/PhpSpreadsheet/pull/3828)
- Recurse directories searching for font file. [Issue #2809](https://github.com/PHPOffice/PhpSpreadsheet/issues/2809) [PR #3830](https://github.com/PHPOffice/PhpSpreadsheet/pull/3830)

## 1.29.0 - 2023-06-15

Expand Down
43 changes: 40 additions & 3 deletions src/PhpSpreadsheet/Shared/Font.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use PhpOffice\PhpSpreadsheet\RichText\RichText;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Font as FontStyle;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;

class Font
{
Expand Down Expand Up @@ -203,15 +205,17 @@ class Font
/**
* Array that can be used to supplement FONT_FILE_NAMES for calculating exact width.
*
* @var array
* @var array<string, array<string, string>>
*/
private static $extraFontArray = [];

/** @param array<string, array<string, string>> $extraFontArray */
public static function setExtraFontArray(array $extraFontArray): void
{
self::$extraFontArray = $extraFontArray;
}

/** @return array<string, array<string, string>> */
public static function getExtraFontArray(): array
{
return self::$extraFontArray;
Expand Down Expand Up @@ -318,7 +322,8 @@ public static function getAutoSizeMethod()

/**
* Set the path to the folder containing .ttf files. There should be a trailing slash.
* Typical locations on variout some platforms:
* Path will be recursively searched for font file.
* Typical locations on various platforms:
* <ul>
* <li>C:/Windows/Fonts/</li>
* <li>/usr/share/fonts/truetype/</li>
Expand Down Expand Up @@ -589,7 +594,7 @@ public static function getTrueTypeFontFileFromFont(FontStyle $font, bool $checkP
}
$fontFileAbsolute = preg_match('~^([A-Za-z]:)?[/\\\\]~', $fontFile) === 1;
if (!$fontFileAbsolute) {
$fontFile = self::$trueTypeFontPath . $separator . $fontFile;
$fontFile = self::findFontFile(self::$trueTypeFontPath, $fontFile) ?? self::$trueTypeFontPath . $separator . $fontFile;
}

// Check if file actually exists
Expand Down Expand Up @@ -698,4 +703,36 @@ public static function getDefaultRowHeightByFont(FontStyle $font): float

return $rowHeight;
}

private static function findFontFile(string $startDirectory, string $desiredFont): ?string
{
$fontPath = null;
if ($startDirectory === '') {
return null;
}
if (file_exists("$startDirectory/$desiredFont")) {
$fontPath = "$startDirectory/$desiredFont";
} else {
$it = new RecursiveDirectoryIterator(
$startDirectory,
RecursiveDirectoryIterator::SKIP_DOTS
| RecursiveDirectoryIterator::FOLLOW_SYMLINKS
);
foreach (
new RecursiveIteratorIterator(
$it,
RecursiveIteratorIterator::LEAVES_ONLY,
RecursiveIteratorIterator::CATCH_GET_CHILD
) as $file
) {
if (basename($file) === $desiredFont) {
$fontPath = $file;

break;
}
}
}

return $fontPath;
}
}
26 changes: 26 additions & 0 deletions tests/PhpSpreadsheetTests/Shared/FontFileNameTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class FontFileNameTest extends TestCase
{
private const DEFAULT_DIRECTORY = 'tests/data/Shared/FakeFonts/Default';
private const MAC_DIRECTORY = 'tests/data/Shared/FakeFonts/Mac';
private const RECURSE_DIRECTORY = 'tests/data/Shared/FakeFonts/Recurse';

private string $holdDirectory;

Expand Down Expand Up @@ -182,4 +183,29 @@ public static function providerOverrideAbsolute(): array
'non-absolute path uses TrueTypeFontPath' => ['cour.ttf', ['name' => 'Courier New']],
];
}

/**
* @dataProvider providerRecurse
*/
public function testRecurseFilenames(string $expected, array $fontArray): void
{
if ($expected === 'exception') {
$this->expectException(SSException::class);
$this->expectExceptionMessage('TrueType Font file not found');
}
Font::setTrueTypeFontPath(self::RECURSE_DIRECTORY);
$font = (new StyleFont())->applyFromArray($fontArray);
$result = Font::getTrueTypeFontFileFromFont($font);
self::assertSame($expected, basename($result));
}

public static function providerRecurse(): array
{
return [
'in subdirectory' => ['arial.ttf', ['name' => 'Arial']],
'in subdirectory bold' => ['arialbd.ttf', ['name' => 'Arial', 'bold' => true]],
'in main directory' => ['cour.ttf', ['name' => 'Courier New']],
'not in main or subdirectory' => ['exception', ['name' => 'Courier New', 'bold' => true]],
];
}
}
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.

0 comments on commit 6f84f41

Please sign in to comment.