Failed Conditions
Push — master ( a2bb82...a189d9 )
by Adrien
10:27 queued 01:00
created

Font::getTextWidthPixelsApprox()   B

Complexity

Conditions 6
Paths 12

Size

Total Lines 47
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 24
CRAP Score 6

Importance

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

268
        $columnWidth = Drawing::pixelsToCellDimension($columnWidth, /** @scrutinizer ignore-type */ $defaultFont);
Loading history...
Bug introduced by
It seems like $columnWidth can also be of type double; however, parameter $pValue of PhpOffice\PhpSpreadsheet...pixelsToCellDimension() does only seem to accept integer, 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

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