mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-08-30 12:07:56 +00:00
Merge branch 'master' into NumberFormat_Improved-Docblocks
This commit is contained in:
@@ -200,6 +200,23 @@ class Font
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* Array that can be used to supplement FONT_FILE_NAMES for calculating exact width.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $extraFontArray = [];
|
||||
|
||||
public static function setExtraFontArray(array $extraFontArray): void
|
||||
{
|
||||
self::$extraFontArray = $extraFontArray;
|
||||
}
|
||||
|
||||
public static function getExtraFontArray(): array
|
||||
{
|
||||
return self::$extraFontArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoSize method.
|
||||
*
|
||||
@@ -403,10 +420,6 @@ class Font
|
||||
*/
|
||||
public static function getTextWidthPixelsExact(string $text, FontStyle $font, int $rotation = 0): int
|
||||
{
|
||||
if (!function_exists('imagettfbbox')) {
|
||||
throw new PhpSpreadsheetException('GD library needs to be enabled');
|
||||
}
|
||||
|
||||
// font size should really be supplied in pixels in GD2,
|
||||
// but since GD2 seems to assume 72dpi, pixels and points are the same
|
||||
$fontFile = self::getTrueTypeFontFileFromFont($font);
|
||||
@@ -532,7 +545,8 @@ class Font
|
||||
}
|
||||
|
||||
$name = $font->getName();
|
||||
if (!isset(self::FONT_FILE_NAMES[$name])) {
|
||||
$fontArray = array_merge(self::FONT_FILE_NAMES, self::$extraFontArray);
|
||||
if (!isset($fontArray[$name])) {
|
||||
throw new PhpSpreadsheetException('Unknown font name "' . $name . '". Cannot map to TrueType font file');
|
||||
}
|
||||
$bold = $font->getBold();
|
||||
@@ -544,7 +558,7 @@ class Font
|
||||
if ($italic) {
|
||||
$index .= 'i';
|
||||
}
|
||||
$fontFile = self::FONT_FILE_NAMES[$name][$index];
|
||||
$fontFile = $fontArray[$name][$index];
|
||||
|
||||
$separator = '';
|
||||
if (mb_strlen(self::$trueTypeFontPath) > 1 && mb_substr(self::$trueTypeFontPath, -1) !== '/' && mb_substr(self::$trueTypeFontPath, -1) !== '\\') {
|
||||
@@ -554,7 +568,31 @@ class Font
|
||||
|
||||
// Check if file actually exists
|
||||
if ($checkPath && !file_exists($fontFile)) {
|
||||
throw new PhpSpreadsheetException('TrueType Font file not found');
|
||||
$alternateName = $name;
|
||||
if ($index !== 'x' && $fontArray[$name][$index] !== $fontArray[$name]['x']) {
|
||||
// Bold but no italic:
|
||||
// Comic Sans
|
||||
// Tahoma
|
||||
// Neither bold nor italic:
|
||||
// Impact
|
||||
// Lucida Console
|
||||
// Lucida Sans Unicode
|
||||
// Microsoft Sans Serif
|
||||
// Symbol
|
||||
if ($index === 'xb') {
|
||||
$alternateName .= ' Bold';
|
||||
} elseif ($index === 'xi') {
|
||||
$alternateName .= ' Italic';
|
||||
} elseif ($fontArray[$name]['xb'] === $fontArray[$name]['xbi']) {
|
||||
$alternateName .= ' Bold';
|
||||
} else {
|
||||
$alternateName .= ' Bold Italic';
|
||||
}
|
||||
}
|
||||
$fontFile = self::$trueTypeFontPath . $separator . $alternateName . '.ttf';
|
||||
if (!file_exists($fontFile)) {
|
||||
throw new PhpSpreadsheetException('TrueType Font file not found');
|
||||
}
|
||||
}
|
||||
|
||||
return $fontFile;
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Shared;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\Exception as SSException;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Font;
|
||||
use PhpOffice\PhpSpreadsheet\Style\Font as StyleFont;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FontFileNameTest extends TestCase
|
||||
{
|
||||
private const DEFAULT_DIRECTORY = 'tests/data/Shared/FakeFonts/Default';
|
||||
private const MAC_DIRECTORY = 'tests/data/Shared/FakeFonts/Mac';
|
||||
|
||||
/** @var string */
|
||||
private $holdDirectory;
|
||||
|
||||
/** @var array */
|
||||
private $holdExtraFontArray;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->holdDirectory = Font::getTrueTypeFontPath();
|
||||
$this->holdExtraFontArray = Font::getExtraFontArray();
|
||||
Font::setExtraFontArray([
|
||||
'Extra Font' => [
|
||||
'x' => 'extrafont.ttf',
|
||||
'xb' => 'extrafontbd.ttf',
|
||||
'xi' => 'extrafonti.ttf',
|
||||
'xbi' => 'extrafontbi.ttf',
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Font::setTrueTypeFontPath($this->holdDirectory);
|
||||
Font::setExtraFontArray($this->holdExtraFontArray);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerDefault
|
||||
*/
|
||||
public function testDefaultFilenames(string $expected, array $fontArray): void
|
||||
{
|
||||
if ($expected === 'exception') {
|
||||
$this->expectException(SSException::class);
|
||||
$this->expectExceptionMessage('TrueType Font file not found');
|
||||
}
|
||||
Font::setTrueTypeFontPath(self::DEFAULT_DIRECTORY);
|
||||
$font = (new StyleFont())->applyFromArray($fontArray);
|
||||
$result = Font::getTrueTypeFontFileFromFont($font);
|
||||
self::assertSame($expected, basename($result));
|
||||
}
|
||||
|
||||
public function providerDefault(): array
|
||||
{
|
||||
return [
|
||||
['arial.ttf', ['name' => 'Arial']],
|
||||
['arialbd.ttf', ['name' => 'Arial', 'bold' => true]],
|
||||
['ariali.ttf', ['name' => 'Arial', 'italic' => true]],
|
||||
['arialbi.ttf', ['name' => 'Arial', 'bold' => true, 'italic' => true]],
|
||||
['cour.ttf', ['name' => 'Courier New']],
|
||||
['courbd.ttf', ['name' => 'Courier New', 'bold' => true]],
|
||||
['couri.ttf', ['name' => 'Courier New', 'italic' => true]],
|
||||
['courbi.ttf', ['name' => 'Courier New', 'bold' => true, 'italic' => true]],
|
||||
['impact.ttf', ['name' => 'Impact']],
|
||||
'no bold impact' => ['impact.ttf', ['name' => 'Impact', 'bold' => true]],
|
||||
'no italic impact' => ['impact.ttf', ['name' => 'Impact', 'italic' => true]],
|
||||
'no bold italic impact' => ['impact.ttf', ['name' => 'Impact', 'bold' => true, 'italic' => true]],
|
||||
['tahoma.ttf', ['name' => 'Tahoma']],
|
||||
['tahomabd.ttf', ['name' => 'Tahoma', 'bold' => true]],
|
||||
'no italic tahoma' => ['tahoma.ttf', ['name' => 'Tahoma', 'italic' => true]],
|
||||
'no bold italic tahoma' => ['tahomabd.ttf', ['name' => 'Tahoma', 'bold' => true, 'italic' => true]],
|
||||
'Times New Roman not in directory for this test' => ['exception', ['name' => 'Times New Roman']],
|
||||
['extrafont.ttf', ['name' => 'Extra Font']],
|
||||
['extrafontbd.ttf', ['name' => 'Extra Font', 'bold' => true]],
|
||||
['extrafonti.ttf', ['name' => 'Extra Font', 'italic' => true]],
|
||||
['extrafontbi.ttf', ['name' => 'Extra Font', 'bold' => true, 'italic' => true]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerMac
|
||||
*/
|
||||
public function testMacFilenames(string $expected, array $fontArray): void
|
||||
{
|
||||
if ($expected === 'exception') {
|
||||
$this->expectException(SSException::class);
|
||||
$this->expectExceptionMessage('TrueType Font file not found');
|
||||
}
|
||||
Font::setTrueTypeFontPath(self::MAC_DIRECTORY);
|
||||
$font = (new StyleFont())->applyFromArray($fontArray);
|
||||
$result = Font::getTrueTypeFontFileFromFont($font);
|
||||
self::assertSame($expected, ucfirst(basename($result))); // allow for Windows case-insensitivity
|
||||
}
|
||||
|
||||
public function providerMac(): array
|
||||
{
|
||||
return [
|
||||
['Arial.ttf', ['name' => 'Arial']],
|
||||
['Arial Bold.ttf', ['name' => 'Arial', 'bold' => true]],
|
||||
['Arial Italic.ttf', ['name' => 'Arial', 'italic' => true]],
|
||||
['Arial Bold Italic.ttf', ['name' => 'Arial', 'bold' => true, 'italic' => true]],
|
||||
['Courier New.ttf', ['name' => 'Courier New']],
|
||||
['Courier New Bold.ttf', ['name' => 'Courier New', 'bold' => true]],
|
||||
['Courier New Italic.ttf', ['name' => 'Courier New', 'italic' => true]],
|
||||
['Courier New Bold Italic.ttf', ['name' => 'Courier New', 'bold' => true, 'italic' => true]],
|
||||
['Impact.ttf', ['name' => 'Impact']],
|
||||
'no bold impact' => ['Impact.ttf', ['name' => 'Impact', 'bold' => true]],
|
||||
'no italic impact' => ['Impact.ttf', ['name' => 'Impact', 'italic' => true]],
|
||||
'no bold italic impact' => ['Impact.ttf', ['name' => 'Impact', 'bold' => true, 'italic' => true]],
|
||||
['Tahoma.ttf', ['name' => 'Tahoma']],
|
||||
['Tahoma Bold.ttf', ['name' => 'Tahoma', 'bold' => true]],
|
||||
'no italic tahoma' => ['Tahoma.ttf', ['name' => 'Tahoma', 'italic' => true]],
|
||||
'no bold italic tahoma' => ['Tahoma Bold.ttf', ['name' => 'Tahoma', 'bold' => true, 'italic' => true]],
|
||||
'Times New Roman not in directory for this test' => ['exception', ['name' => 'Times New Roman']],
|
||||
['Extra Font.ttf', ['name' => 'Extra Font']],
|
||||
['Extra Font Bold.ttf', ['name' => 'Extra Font', 'bold' => true]],
|
||||
['Extra Font Italic.ttf', ['name' => 'Extra Font', 'italic' => true]],
|
||||
['Extra Font Bold Italic.ttf', ['name' => 'Extra Font', 'bold' => true, 'italic' => true]],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerOverride
|
||||
*/
|
||||
public function testOverrideFilenames(string $expected, array $fontArray): void
|
||||
{
|
||||
Font::setTrueTypeFontPath(self::DEFAULT_DIRECTORY);
|
||||
Font::setExtraFontArray([
|
||||
'Arial' => [
|
||||
'x' => 'extrafont.ttf',
|
||||
'xb' => 'extrafontbd.ttf',
|
||||
'xi' => 'extrafonti.ttf',
|
||||
'xbi' => 'extrafontbi.ttf',
|
||||
],
|
||||
]);
|
||||
$font = (new StyleFont())->applyFromArray($fontArray);
|
||||
$result = Font::getTrueTypeFontFileFromFont($font);
|
||||
self::assertSame($expected, basename($result));
|
||||
}
|
||||
|
||||
public function providerOverride(): array
|
||||
{
|
||||
return [
|
||||
['extrafont.ttf', ['name' => 'Arial']],
|
||||
['extrafontbd.ttf', ['name' => 'Arial', 'bold' => true]],
|
||||
['extrafonti.ttf', ['name' => 'Arial', 'italic' => true]],
|
||||
['extrafontbi.ttf', ['name' => 'Arial', 'bold' => true, 'italic' => true]],
|
||||
['cour.ttf', ['name' => 'Courier New']],
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user