Passed
Push — master ( 75dfcb...5ec0e3 )
by Adrien
27:56
created

Font::fontSizeToPixels()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Shared;
4
5
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
6
use PhpOffice\PhpSpreadsheet\RichText\RichText;
7
8
class Font
9
{
10
    // Methods for resolving autosize value
11
    const AUTOSIZE_METHOD_APPROX = 'approx';
12
    const AUTOSIZE_METHOD_EXACT = 'exact';
13
14
    private static $autoSizeMethods = [
15
        self::AUTOSIZE_METHOD_APPROX,
16
        self::AUTOSIZE_METHOD_EXACT,
17
    ];
18
19
    /** Character set codes used by BIFF5-8 in Font records */
20
    const CHARSET_ANSI_LATIN = 0x00;
21
    const CHARSET_SYSTEM_DEFAULT = 0x01;
22
    const CHARSET_SYMBOL = 0x02;
23
    const CHARSET_APPLE_ROMAN = 0x4D;
24
    const CHARSET_ANSI_JAPANESE_SHIFTJIS = 0x80;
25
    const CHARSET_ANSI_KOREAN_HANGUL = 0x81;
26
    const CHARSET_ANSI_KOREAN_JOHAB = 0x82;
27
    const CHARSET_ANSI_CHINESE_SIMIPLIFIED = 0x86; //    gb2312
28
    const CHARSET_ANSI_CHINESE_TRADITIONAL = 0x88; //    big5
29
    const CHARSET_ANSI_GREEK = 0xA1;
30
    const CHARSET_ANSI_TURKISH = 0xA2;
31
    const CHARSET_ANSI_VIETNAMESE = 0xA3;
32
    const CHARSET_ANSI_HEBREW = 0xB1;
33
    const CHARSET_ANSI_ARABIC = 0xB2;
34
    const CHARSET_ANSI_BALTIC = 0xBA;
35
    const CHARSET_ANSI_CYRILLIC = 0xCC;
36
    const CHARSET_ANSI_THAI = 0xDD;
37
    const CHARSET_ANSI_LATIN_II = 0xEE;
38
    const CHARSET_OEM_LATIN_I = 0xFF;
39
40
    //  XXX: Constants created!
41
    /** Font filenames */
42
    const ARIAL = 'arial.ttf';
43
    const ARIAL_BOLD = 'arialbd.ttf';
44
    const ARIAL_ITALIC = 'ariali.ttf';
45
    const ARIAL_BOLD_ITALIC = 'arialbi.ttf';
46
47
    const CALIBRI = 'CALIBRI.TTF';
48
    const CALIBRI_BOLD = 'CALIBRIB.TTF';
49
    const CALIBRI_ITALIC = 'CALIBRII.TTF';
50
    const CALIBRI_BOLD_ITALIC = 'CALIBRIZ.TTF';
51
52
    const COMIC_SANS_MS = 'comic.ttf';
53
    const COMIC_SANS_MS_BOLD = 'comicbd.ttf';
54
55
    const COURIER_NEW = 'cour.ttf';
56
    const COURIER_NEW_BOLD = 'courbd.ttf';
57
    const COURIER_NEW_ITALIC = 'couri.ttf';
58
    const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf';
59
60
    const GEORGIA = 'georgia.ttf';
61
    const GEORGIA_BOLD = 'georgiab.ttf';
62
    const GEORGIA_ITALIC = 'georgiai.ttf';
63
    const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf';
64
65
    const IMPACT = 'impact.ttf';
66
67
    const LIBERATION_SANS = 'LiberationSans-Regular.ttf';
68
    const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf';
69
    const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf';
70
    const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf';
71
72
    const LUCIDA_CONSOLE = 'lucon.ttf';
73
    const LUCIDA_SANS_UNICODE = 'l_10646.ttf';
74
75
    const MICROSOFT_SANS_SERIF = 'micross.ttf';
76
77
    const PALATINO_LINOTYPE = 'pala.ttf';
78
    const PALATINO_LINOTYPE_BOLD = 'palab.ttf';
79
    const PALATINO_LINOTYPE_ITALIC = 'palai.ttf';
80
    const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf';
81
82
    const SYMBOL = 'symbol.ttf';
83
84
    const TAHOMA = 'tahoma.ttf';
85
    const TAHOMA_BOLD = 'tahomabd.ttf';
86
87
    const TIMES_NEW_ROMAN = 'times.ttf';
88
    const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf';
89
    const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf';
90
    const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf';
91
92
    const TREBUCHET_MS = 'trebuc.ttf';
93
    const TREBUCHET_MS_BOLD = 'trebucbd.ttf';
94
    const TREBUCHET_MS_ITALIC = 'trebucit.ttf';
95
    const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf';
96
97
    const VERDANA = 'verdana.ttf';
98
    const VERDANA_BOLD = 'verdanab.ttf';
99
    const VERDANA_ITALIC = 'verdanai.ttf';
100
    const VERDANA_BOLD_ITALIC = 'verdanaz.ttf';
101
102
    /**
103
     * AutoSize method.
104
     *
105
     * @var string
106
     */
107
    private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX;
108
109
    /**
110
     * Path to folder containing TrueType font .ttf files.
111
     *
112
     * @var string
113
     */
114
    private static $trueTypeFontPath = null;
115
116
    /**
117
     * How wide is a default column for a given default font and size?
118
     * Empirical data found by inspecting real Excel files and reading off the pixel width
119
     * in Microsoft Office Excel 2007.
120
     *
121
     * @var array
122
     */
123
    public static $defaultColumnWidths = [
124
        'Arial' => [
125
            1 => ['px' => 24, 'width' => 12.00000000],
126
            2 => ['px' => 24, 'width' => 12.00000000],
127
            3 => ['px' => 32, 'width' => 10.66406250],
128
            4 => ['px' => 32, 'width' => 10.66406250],
129
            5 => ['px' => 40, 'width' => 10.00000000],
130
            6 => ['px' => 48, 'width' => 9.59765625],
131
            7 => ['px' => 48, 'width' => 9.59765625],
132
            8 => ['px' => 56, 'width' => 9.33203125],
133
            9 => ['px' => 64, 'width' => 9.14062500],
134
            10 => ['px' => 64, 'width' => 9.14062500],
135
        ],
136
        'Calibri' => [
137
            1 => ['px' => 24, 'width' => 12.00000000],
138
            2 => ['px' => 24, 'width' => 12.00000000],
139
            3 => ['px' => 32, 'width' => 10.66406250],
140
            4 => ['px' => 32, 'width' => 10.66406250],
141
            5 => ['px' => 40, 'width' => 10.00000000],
142
            6 => ['px' => 48, 'width' => 9.59765625],
143
            7 => ['px' => 48, 'width' => 9.59765625],
144
            8 => ['px' => 56, 'width' => 9.33203125],
145
            9 => ['px' => 56, 'width' => 9.33203125],
146
            10 => ['px' => 64, 'width' => 9.14062500],
147
            11 => ['px' => 64, 'width' => 9.14062500],
148
        ],
149
        'Verdana' => [
150
            1 => ['px' => 24, 'width' => 12.00000000],
151
            2 => ['px' => 24, 'width' => 12.00000000],
152
            3 => ['px' => 32, 'width' => 10.66406250],
153
            4 => ['px' => 32, 'width' => 10.66406250],
154
            5 => ['px' => 40, 'width' => 10.00000000],
155
            6 => ['px' => 48, 'width' => 9.59765625],
156
            7 => ['px' => 48, 'width' => 9.59765625],
157
            8 => ['px' => 64, 'width' => 9.14062500],
158
            9 => ['px' => 72, 'width' => 9.00000000],
159
            10 => ['px' => 72, 'width' => 9.00000000],
160
        ],
161
    ];
162
163
    /**
164
     * Set autoSize method.
165
     *
166
     * @param string $pValue see self::AUTOSIZE_METHOD_*
167
     *
168
     * @return bool Success or failure
169
     */
170 2
    public static function setAutoSizeMethod($pValue)
171
    {
172 2
        if (!in_array($pValue, self::$autoSizeMethods)) {
173 1
            return false;
174
        }
175 1
        self::$autoSizeMethod = $pValue;
176
177 1
        return true;
178
    }
179
180
    /**
181
     * Get autoSize method.
182
     *
183
     * @return string
184
     */
185 1
    public static function getAutoSizeMethod()
186
    {
187 1
        return self::$autoSizeMethod;
188
    }
189
190
    /**
191
     * Set the path to the folder containing .ttf files. There should be a trailing slash.
192
     * Typical locations on variout some platforms:
193
     *    <ul>
194
     *        <li>C:/Windows/Fonts/</li>
195
     *        <li>/usr/share/fonts/truetype/</li>
196
     *        <li>~/.fonts/</li>
197
     * </ul>.
198
     *
199
     * @param string $pValue
200
     */
201
    public static function setTrueTypeFontPath($pValue)
202
    {
203
        self::$trueTypeFontPath = $pValue;
204
    }
205
206
    /**
207
     * Get the path to the folder containing .ttf files.
208
     *
209
     * @return string
210
     */
211
    public static function getTrueTypeFontPath()
212
    {
213
        return self::$trueTypeFontPath;
214
    }
215
216
    /**
217
     * Calculate an (approximate) OpenXML column width, based on font size and text contained.
218
     *
219
     * @param \PhpOffice\PhpSpreadsheet\Style\Font $font Font object
220
     * @param RichText|string $cellText Text to calculate width
221
     * @param int $rotation Rotation angle
222
     * @param null|\PhpOffice\PhpSpreadsheet\Style\Font $defaultFont Font object
223
     *
224
     * @return int Column width
225
     */
226 13
    public static function calculateColumnWidth(\PhpOffice\PhpSpreadsheet\Style\Font $font, $cellText = '', $rotation = 0, \PhpOffice\PhpSpreadsheet\Style\Font $defaultFont = null)
227
    {
228
        // If it is rich text, use plain text
229 13
        if ($cellText instanceof RichText) {
230
            $cellText = $cellText->getPlainText();
231
        }
232
233
        // Special case if there are one or more newline characters ("\n")
234 13
        if (strpos($cellText, "\n") !== false) {
235 1
            $lineTexts = explode("\n", $cellText);
236 1
            $lineWidths = [];
237 1
            foreach ($lineTexts as $lineText) {
238 1
                $lineWidths[] = self::calculateColumnWidth($font, $lineText, $rotation = 0, $defaultFont);
239
            }
240
241 1
            return max($lineWidths); // width of longest line in cell
242
        }
243
244
        // Try to get the exact text width in pixels
245 13
        $approximate = self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX;
246 13
        if (!$approximate) {
247
            $columnWidthAdjust = ceil(self::getTextWidthPixelsExact('n', $font, 0) * 1.07);
248
249
            try {
250
                // Width of text in pixels excl. padding
251
                // and addition because Excel adds some padding, just use approx width of 'n' glyph
252
                $columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation) + $columnWidthAdjust;
253
            } catch (PhpSpreadsheetException $e) {
254
                $approximate = true;
255
            }
256
        }
257
258 13
        if ($approximate) {
259 13
            $columnWidthAdjust = self::getTextWidthPixelsApprox('n', $font, 0);
260
            // Width of text in pixels excl. padding, approximation
261
            // and addition because Excel adds some padding, just use approx width of 'n' glyph
262 13
            $columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation) + $columnWidthAdjust;
263
        }
264
265
        // Convert from pixel width to column width
266 13
        $columnWidth = Drawing::pixelsToCellDimension($columnWidth, $defaultFont);
1 ignored issue
show
Comprehensibility Best Practice introduced by
The variable $columnWidth does not seem to be defined for all execution paths leading up to this point.
Loading history...
Bug introduced by
It seems like $defaultFont can also be of type null; however, parameter $pDefaultFont of PhpOffice\PhpSpreadsheet...pixelsToCellDimension() does only seem to accept PhpOffice\PhpSpreadsheet\Style\Font, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

266
        $columnWidth = Drawing::pixelsToCellDimension($columnWidth, /** @scrutinizer ignore-type */ $defaultFont);
Loading history...
267
268
        // Return
269 13
        return round($columnWidth, 6);
270
    }
271
272
    /**
273
     * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle.
274
     *
275
     * @param string $text
276
     * @param \PhpOffice\PhpSpreadsheet\Style\Font
277
     * @param int $rotation
278
     *
279
     * @throws PhpSpreadsheetException
280
     *
281
     * @return int
282
     */
283
    public static function getTextWidthPixelsExact($text, \PhpOffice\PhpSpreadsheet\Style\Font $font, $rotation = 0)
284
    {
285
        if (!function_exists('imagettfbbox')) {
286
            throw new PhpSpreadsheetException('GD library needs to be enabled');
287
        }
288
289
        // font size should really be supplied in pixels in GD2,
290
        // but since GD2 seems to assume 72dpi, pixels and points are the same
291
        $fontFile = self::getTrueTypeFontFileFromFont($font);
292
        $textBox = imagettfbbox($font->getSize(), $rotation, $fontFile, $text);
293
294
        // Get corners positions
295
        $lowerLeftCornerX = $textBox[0];
296
        $lowerRightCornerX = $textBox[2];
297
        $upperRightCornerX = $textBox[4];
298
        $upperLeftCornerX = $textBox[6];
299
300
        // Consider the rotation when calculating the width
301
        return max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX);
302
    }
303
304
    /**
305
     * Get approximate width in pixels for a string of text in a certain font at a certain rotation angle.
306
     *
307
     * @param string $columnText
308
     * @param \PhpOffice\PhpSpreadsheet\Style\Font $font
309
     * @param int $rotation
310
     *
311
     * @return int Text width in pixels (no padding added)
312
     */
313 13
    public static function getTextWidthPixelsApprox($columnText, \PhpOffice\PhpSpreadsheet\Style\Font $font, $rotation = 0)
314
    {
315 13
        $fontName = $font->getName();
316 13
        $fontSize = $font->getSize();
317
318
        // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size.
319 13
        switch ($fontName) {
320 13
            case 'Calibri':
321
                // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font.
322 11
                $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText));
323 11
                $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
324 11
                break;
325 12
            case 'Arial':
326
                // value 8 was set because of experience in different exports at Arial 10 font.
327 2
                $columnWidth = (int) (8 * StringHelper::countCharacters($columnText));
328 2
                $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
329 2
                break;
330 10
            case 'Verdana':
331
                // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font.
332
                $columnWidth = (int) (8 * StringHelper::countCharacters($columnText));
333
                $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size
334
                break;
335
            default:
336
                // just assume Calibri
337 10
                $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText));
338 10
                $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size
339 10
                break;
340
        }
341
342
        // Calculate approximate rotated column width
343 13
        if ($rotation !== 0) {
344
            if ($rotation == -165) {
345
                // stacked text
346
                $columnWidth = 4; // approximation
347
            } else {
348
                // rotated text
349
                $columnWidth = $columnWidth * cos(deg2rad($rotation))
350
                                + $fontSize * abs(sin(deg2rad($rotation))) / 5; // approximation
351
            }
352
        }
353
354
        // pixel width is an integer
355 13
        return (int) $columnWidth;
356
    }
357
358
    /**
359
     * Calculate an (approximate) pixel size, based on a font points size.
360
     *
361
     * @param int $fontSizeInPoints Font size (in points)
362
     *
363
     * @return int Font size (in pixels)
364
     */
365 21
    public static function fontSizeToPixels($fontSizeInPoints)
366
    {
367 21
        return (int) ((4 / 3) * $fontSizeInPoints);
368
    }
369
370
    /**
371
     * Calculate an (approximate) pixel size, based on inch size.
372
     *
373
     * @param int $sizeInInch Font size (in inch)
374
     *
375
     * @return int Size (in pixels)
376
     */
377 5
    public static function inchSizeToPixels($sizeInInch)
378
    {
379 5
        return $sizeInInch * 96;
380
    }
381
382
    /**
383
     * Calculate an (approximate) pixel size, based on centimeter size.
384
     *
385
     * @param int $sizeInCm Font size (in centimeters)
386
     *
387
     * @return float Size (in pixels)
388
     */
389 5
    public static function centimeterSizeToPixels($sizeInCm)
390
    {
391 5
        return $sizeInCm * 37.795275591;
392
    }
393
394
    /**
395
     * Returns the font path given the font.
396
     *
397
     * @param \PhpOffice\PhpSpreadsheet\Style\Font $font
398
     *
399
     * @return string Path to TrueType font file
400
     */
401
    public static function getTrueTypeFontFileFromFont($font)
402
    {
403
        if (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath)) {
404
            throw new PhpSpreadsheetException('Valid directory to TrueType Font files not specified');
405
        }
406
407
        $name = $font->getName();
408
        $bold = $font->getBold();
409
        $italic = $font->getItalic();
410
411
        // Check if we can map font to true type font file
412
        switch ($name) {
413
            case 'Arial':
414
                $fontFile = (
415
                    $bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD)
416
                          : ($italic ? self::ARIAL_ITALIC : self::ARIAL)
417
                );
418
419
                break;
420
            case 'Calibri':
421
                $fontFile = (
422
                    $bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD)
423
                          : ($italic ? self::CALIBRI_ITALIC : self::CALIBRI)
424
                );
425
426
                break;
427
            case 'Courier New':
428
                $fontFile = (
429
                    $bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD)
430
                          : ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW)
431
                );
432
433
                break;
434
            case 'Comic Sans MS':
435
                $fontFile = (
436
                    $bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS
437
                );
438
439
                break;
440
            case 'Georgia':
441
                $fontFile = (
442
                    $bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD)
443
                          : ($italic ? self::GEORGIA_ITALIC : self::GEORGIA)
444
                );
445
446
                break;
447
            case 'Impact':
448
                $fontFile = self::IMPACT;
449
450
                break;
451
            case 'Liberation Sans':
452
                $fontFile = (
453
                    $bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD)
454
                          : ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS)
455
                );
456
457
                break;
458
            case 'Lucida Console':
459
                $fontFile = self::LUCIDA_CONSOLE;
460
461
                break;
462
            case 'Lucida Sans Unicode':
463
                $fontFile = self::LUCIDA_SANS_UNICODE;
464
465
                break;
466
            case 'Microsoft Sans Serif':
467
                $fontFile = self::MICROSOFT_SANS_SERIF;
468
469
                break;
470
            case 'Palatino Linotype':
471
                $fontFile = (
472
                    $bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD)
473
                          : ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE)
474
                );
475
476
                break;
477
            case 'Symbol':
478
                $fontFile = self::SYMBOL;
479
480
                break;
481
            case 'Tahoma':
482
                $fontFile = (
483
                    $bold ? self::TAHOMA_BOLD : self::TAHOMA
484
                );
485
486
                break;
487
            case 'Times New Roman':
488
                $fontFile = (
489
                    $bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD)
490
                          : ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN)
491
                );
492
493
                break;
494
            case 'Trebuchet MS':
495
                $fontFile = (
496
                    $bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD)
497
                          : ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS)
498
                );
499
500
                break;
501
            case 'Verdana':
502
                $fontFile = (
503
                    $bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD)
504
                          : ($italic ? self::VERDANA_ITALIC : self::VERDANA)
505
                );
506
507
                break;
508
            default:
509
                throw new PhpSpreadsheetException('Unknown font name "' . $name . '". Cannot map to TrueType font file');
510
511
                break;
512
        }
513
514
        $fontFile = self::$trueTypeFontPath . $fontFile;
515
516
        // Check if file actually exists
517
        if (!file_exists($fontFile)) {
518
            throw new PhpSpreadsheetException('TrueType Font file not found');
519
        }
520
521
        return $fontFile;
522
    }
523
524
    /**
525
     * Returns the associated charset for the font name.
526
     *
527
     * @param string $name Font name
528
     *
529
     * @return int Character set code
530
     */
531 44
    public static function getCharsetFromFontName($name)
532
    {
533 44
        switch ($name) {
534
            // Add more cases. Check FONT records in real Excel files.
535 44
            case 'EucrosiaUPC':
536
                return self::CHARSET_ANSI_THAI;
537 44
            case 'Wingdings':
538
                return self::CHARSET_SYMBOL;
539 44
            case 'Wingdings 2':
540
                return self::CHARSET_SYMBOL;
541 44
            case 'Wingdings 3':
542
                return self::CHARSET_SYMBOL;
543
            default:
544 44
                return self::CHARSET_ANSI_LATIN;
545
        }
546
    }
547
548
    /**
549
     * Get the effective column width for columns without a column dimension or column with width -1
550
     * For example, for Calibri 11 this is 9.140625 (64 px).
551
     *
552
     * @param \PhpOffice\PhpSpreadsheet\Style\Font $font The workbooks default font
553
     * @param bool $pPixels true = return column width in pixels, false = return in OOXML units
554
     *
555
     * @return mixed Column width
556
     */
557 43
    public static function getDefaultColumnWidthByFont(\PhpOffice\PhpSpreadsheet\Style\Font $font, $pPixels = false)
558
    {
559 43
        if (isset(self::$defaultColumnWidths[$font->getName()][$font->getSize()])) {
560
            // Exact width can be determined
561 43
            $columnWidth = $pPixels ?
562 6
                self::$defaultColumnWidths[$font->getName()][$font->getSize()]['px']
563 43
                    : self::$defaultColumnWidths[$font->getName()][$font->getSize()]['width'];
564
        } else {
565
            // We don't have data for this particular font and size, use approximation by
566
            // extrapolating from Calibri 11
567
            $columnWidth = $pPixels ?
568
                self::$defaultColumnWidths['Calibri'][11]['px']
569
                    : self::$defaultColumnWidths['Calibri'][11]['width'];
570
            $columnWidth = $columnWidth * $font->getSize() / 11;
571
572
            // Round pixels to closest integer
573
            if ($pPixels) {
574
                $columnWidth = (int) round($columnWidth);
575
            }
576
        }
577
578 43
        return $columnWidth;
579
    }
580
581
    /**
582
     * Get the effective row height for rows without a row dimension or rows with height -1
583
     * For example, for Calibri 11 this is 15 points.
584
     *
585
     * @param \PhpOffice\PhpSpreadsheet\Style\Font $font The workbooks default font
586
     *
587
     * @return float Row height in points
588
     */
589 18
    public static function getDefaultRowHeightByFont(\PhpOffice\PhpSpreadsheet\Style\Font $font)
590
    {
591 18
        switch ($font->getName()) {
592 18
            case 'Arial':
593
                switch ($font->getSize()) {
594
                    case 10:
595
                        // inspection of Arial 10 workbook says 12.75pt ~17px
596
                        $rowHeight = 12.75;
597
598
                        break;
599
                    case 9:
600
                        // inspection of Arial 9 workbook says 12.00pt ~16px
601
                        $rowHeight = 12;
602
603
                        break;
604
                    case 8:
605
                        // inspection of Arial 8 workbook says 11.25pt ~15px
606
                        $rowHeight = 11.25;
607
608
                        break;
609
                    case 7:
610
                        // inspection of Arial 7 workbook says 9.00pt ~12px
611
                        $rowHeight = 9;
612
613
                        break;
614
                    case 6:
615
                    case 5:
616
                        // inspection of Arial 5,6 workbook says 8.25pt ~11px
617
                        $rowHeight = 8.25;
618
619
                        break;
620
                    case 4:
621
                        // inspection of Arial 4 workbook says 6.75pt ~9px
622
                        $rowHeight = 6.75;
623
624
                        break;
625
                    case 3:
626
                        // inspection of Arial 3 workbook says 6.00pt ~8px
627
                        $rowHeight = 6;
628
629
                        break;
630
                    case 2:
631
                    case 1:
632
                        // inspection of Arial 1,2 workbook says 5.25pt ~7px
633
                        $rowHeight = 5.25;
634
635
                        break;
636
                    default:
637
                        // use Arial 10 workbook as an approximation, extrapolation
638
                        $rowHeight = 12.75 * $font->getSize() / 10;
639
640
                        break;
641
                }
642
643
                break;
644 18
            case 'Calibri':
645 18
                switch ($font->getSize()) {
646 18
                    case 11:
647
                        // inspection of Calibri 11 workbook says 15.00pt ~20px
648 18
                        $rowHeight = 15;
649
650 18
                        break;
651
                    case 10:
652
                        // inspection of Calibri 10 workbook says 12.75pt ~17px
653
                        $rowHeight = 12.75;
654
655
                        break;
656
                    case 9:
657
                        // inspection of Calibri 9 workbook says 12.00pt ~16px
658
                        $rowHeight = 12;
659
660
                        break;
661
                    case 8:
662
                        // inspection of Calibri 8 workbook says 11.25pt ~15px
663
                        $rowHeight = 11.25;
664
665
                        break;
666
                    case 7:
667
                        // inspection of Calibri 7 workbook says 9.00pt ~12px
668
                        $rowHeight = 9;
669
670
                        break;
671
                    case 6:
672
                    case 5:
673
                        // inspection of Calibri 5,6 workbook says 8.25pt ~11px
674
                        $rowHeight = 8.25;
675
676
                        break;
677
                    case 4:
678
                        // inspection of Calibri 4 workbook says 6.75pt ~9px
679
                        $rowHeight = 6.75;
680
681
                        break;
682
                    case 3:
683
                        // inspection of Calibri 3 workbook says 6.00pt ~8px
684
                        $rowHeight = 6.00;
685
686
                        break;
687
                    case 2:
688
                    case 1:
689
                        // inspection of Calibri 1,2 workbook says 5.25pt ~7px
690
                        $rowHeight = 5.25;
691
692
                        break;
693
                    default:
694
                        // use Calibri 11 workbook as an approximation, extrapolation
695
                        $rowHeight = 15 * $font->getSize() / 11;
696
697
                        break;
698
                }
699
700 18
                break;
701
            case 'Verdana':
702
                switch ($font->getSize()) {
703
                    case 10:
704
                        // inspection of Verdana 10 workbook says 12.75pt ~17px
705
                        $rowHeight = 12.75;
706
707
                        break;
708
                    case 9:
709
                        // inspection of Verdana 9 workbook says 11.25pt ~15px
710
                        $rowHeight = 11.25;
711
712
                        break;
713
                    case 8:
714
                        // inspection of Verdana 8 workbook says 10.50pt ~14px
715
                        $rowHeight = 10.50;
716
717
                        break;
718
                    case 7:
719
                        // inspection of Verdana 7 workbook says 9.00pt ~12px
720
                        $rowHeight = 9.00;
721
722
                        break;
723
                    case 6:
724
                    case 5:
725
                        // inspection of Verdana 5,6 workbook says 8.25pt ~11px
726
                        $rowHeight = 8.25;
727
728
                        break;
729
                    case 4:
730
                        // inspection of Verdana 4 workbook says 6.75pt ~9px
731
                        $rowHeight = 6.75;
732
733
                        break;
734
                    case 3:
735
                        // inspection of Verdana 3 workbook says 6.00pt ~8px
736
                        $rowHeight = 6;
737
738
                        break;
739
                    case 2:
740
                    case 1:
741
                        // inspection of Verdana 1,2 workbook says 5.25pt ~7px
742
                        $rowHeight = 5.25;
743
744
                        break;
745
                    default:
746
                        // use Verdana 10 workbook as an approximation, extrapolation
747
                        $rowHeight = 12.75 * $font->getSize() / 10;
748
749
                        break;
750
                }
751
752
                break;
753
            default:
754
                // just use Calibri as an approximation
755
                $rowHeight = 15 * $font->getSize() / 11;
756
757
                break;
758
        }
759
760 18
        return $rowHeight;
761
    }
762
}
763