See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]
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 use PhpOffice\PhpSpreadsheet\Style\Font as FontStyle; 9 10 class Font 11 { 12 // Methods for resolving autosize value 13 const AUTOSIZE_METHOD_APPROX = 'approx'; 14 const AUTOSIZE_METHOD_EXACT = 'exact'; 15 16 private const AUTOSIZE_METHODS = [ 17 self::AUTOSIZE_METHOD_APPROX, 18 self::AUTOSIZE_METHOD_EXACT, 19 ]; 20 21 /** Character set codes used by BIFF5-8 in Font records */ 22 const CHARSET_ANSI_LATIN = 0x00; 23 const CHARSET_SYSTEM_DEFAULT = 0x01; 24 const CHARSET_SYMBOL = 0x02; 25 const CHARSET_APPLE_ROMAN = 0x4D; 26 const CHARSET_ANSI_JAPANESE_SHIFTJIS = 0x80; 27 const CHARSET_ANSI_KOREAN_HANGUL = 0x81; 28 const CHARSET_ANSI_KOREAN_JOHAB = 0x82; 29 const CHARSET_ANSI_CHINESE_SIMIPLIFIED = 0x86; // gb2312 30 const CHARSET_ANSI_CHINESE_TRADITIONAL = 0x88; // big5 31 const CHARSET_ANSI_GREEK = 0xA1; 32 const CHARSET_ANSI_TURKISH = 0xA2; 33 const CHARSET_ANSI_VIETNAMESE = 0xA3; 34 const CHARSET_ANSI_HEBREW = 0xB1; 35 const CHARSET_ANSI_ARABIC = 0xB2; 36 const CHARSET_ANSI_BALTIC = 0xBA; 37 const CHARSET_ANSI_CYRILLIC = 0xCC; 38 const CHARSET_ANSI_THAI = 0xDD; 39 const CHARSET_ANSI_LATIN_II = 0xEE; 40 const CHARSET_OEM_LATIN_I = 0xFF; 41 42 // XXX: Constants created! 43 /** Font filenames */ 44 const ARIAL = 'arial.ttf'; 45 const ARIAL_BOLD = 'arialbd.ttf'; 46 const ARIAL_ITALIC = 'ariali.ttf'; 47 const ARIAL_BOLD_ITALIC = 'arialbi.ttf'; 48 49 const CALIBRI = 'calibri.ttf'; 50 const CALIBRI_BOLD = 'calibrib.ttf'; 51 const CALIBRI_ITALIC = 'calibrii.ttf'; 52 const CALIBRI_BOLD_ITALIC = 'calibriz.ttf'; 53 54 const COMIC_SANS_MS = 'comic.ttf'; 55 const COMIC_SANS_MS_BOLD = 'comicbd.ttf'; 56 57 const COURIER_NEW = 'cour.ttf'; 58 const COURIER_NEW_BOLD = 'courbd.ttf'; 59 const COURIER_NEW_ITALIC = 'couri.ttf'; 60 const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf'; 61 62 const GEORGIA = 'georgia.ttf'; 63 const GEORGIA_BOLD = 'georgiab.ttf'; 64 const GEORGIA_ITALIC = 'georgiai.ttf'; 65 const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf'; 66 67 const IMPACT = 'impact.ttf'; 68 69 const LIBERATION_SANS = 'LiberationSans-Regular.ttf'; 70 const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf'; 71 const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf'; 72 const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf'; 73 74 const LUCIDA_CONSOLE = 'lucon.ttf'; 75 const LUCIDA_SANS_UNICODE = 'l_10646.ttf'; 76 77 const MICROSOFT_SANS_SERIF = 'micross.ttf'; 78 79 const PALATINO_LINOTYPE = 'pala.ttf'; 80 const PALATINO_LINOTYPE_BOLD = 'palab.ttf'; 81 const PALATINO_LINOTYPE_ITALIC = 'palai.ttf'; 82 const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf'; 83 84 const SYMBOL = 'symbol.ttf'; 85 86 const TAHOMA = 'tahoma.ttf'; 87 const TAHOMA_BOLD = 'tahomabd.ttf'; 88 89 const TIMES_NEW_ROMAN = 'times.ttf'; 90 const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf'; 91 const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf'; 92 const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf'; 93 94 const TREBUCHET_MS = 'trebuc.ttf'; 95 const TREBUCHET_MS_BOLD = 'trebucbd.ttf'; 96 const TREBUCHET_MS_ITALIC = 'trebucit.ttf'; 97 const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf'; 98 99 const VERDANA = 'verdana.ttf'; 100 const VERDANA_BOLD = 'verdanab.ttf'; 101 const VERDANA_ITALIC = 'verdanai.ttf'; 102 const VERDANA_BOLD_ITALIC = 'verdanaz.ttf'; 103 104 const FONT_FILE_NAMES = [ 105 'Arial' => [ 106 'x' => self::ARIAL, 107 'xb' => self::ARIAL_BOLD, 108 'xi' => self::ARIAL_ITALIC, 109 'xbi' => self::ARIAL_BOLD_ITALIC, 110 ], 111 'Calibri' => [ 112 'x' => self::CALIBRI, 113 'xb' => self::CALIBRI_BOLD, 114 'xi' => self::CALIBRI_ITALIC, 115 'xbi' => self::CALIBRI_BOLD_ITALIC, 116 ], 117 'Comic Sans MS' => [ 118 'x' => self::COMIC_SANS_MS, 119 'xb' => self::COMIC_SANS_MS_BOLD, 120 'xi' => self::COMIC_SANS_MS, 121 'xbi' => self::COMIC_SANS_MS_BOLD, 122 ], 123 'Courier New' => [ 124 'x' => self::COURIER_NEW, 125 'xb' => self::COURIER_NEW_BOLD, 126 'xi' => self::COURIER_NEW_ITALIC, 127 'xbi' => self::COURIER_NEW_BOLD_ITALIC, 128 ], 129 'Georgia' => [ 130 'x' => self::GEORGIA, 131 'xb' => self::GEORGIA_BOLD, 132 'xi' => self::GEORGIA_ITALIC, 133 'xbi' => self::GEORGIA_BOLD_ITALIC, 134 ], 135 'Impact' => [ 136 'x' => self::IMPACT, 137 'xb' => self::IMPACT, 138 'xi' => self::IMPACT, 139 'xbi' => self::IMPACT, 140 ], 141 'Liberation Sans' => [ 142 'x' => self::LIBERATION_SANS, 143 'xb' => self::LIBERATION_SANS_BOLD, 144 'xi' => self::LIBERATION_SANS_ITALIC, 145 'xbi' => self::LIBERATION_SANS_BOLD_ITALIC, 146 ], 147 'Lucida Console' => [ 148 'x' => self::LUCIDA_CONSOLE, 149 'xb' => self::LUCIDA_CONSOLE, 150 'xi' => self::LUCIDA_CONSOLE, 151 'xbi' => self::LUCIDA_CONSOLE, 152 ], 153 'Lucida Sans Unicode' => [ 154 'x' => self::LUCIDA_SANS_UNICODE, 155 'xb' => self::LUCIDA_SANS_UNICODE, 156 'xi' => self::LUCIDA_SANS_UNICODE, 157 'xbi' => self::LUCIDA_SANS_UNICODE, 158 ], 159 'Microsoft Sans Serif' => [ 160 'x' => self::MICROSOFT_SANS_SERIF, 161 'xb' => self::MICROSOFT_SANS_SERIF, 162 'xi' => self::MICROSOFT_SANS_SERIF, 163 'xbi' => self::MICROSOFT_SANS_SERIF, 164 ], 165 'Palatino Linotype' => [ 166 'x' => self::PALATINO_LINOTYPE, 167 'xb' => self::PALATINO_LINOTYPE_BOLD, 168 'xi' => self::PALATINO_LINOTYPE_ITALIC, 169 'xbi' => self::PALATINO_LINOTYPE_BOLD_ITALIC, 170 ], 171 'Symbol' => [ 172 'x' => self::SYMBOL, 173 'xb' => self::SYMBOL, 174 'xi' => self::SYMBOL, 175 'xbi' => self::SYMBOL, 176 ], 177 'Tahoma' => [ 178 'x' => self::TAHOMA, 179 'xb' => self::TAHOMA_BOLD, 180 'xi' => self::TAHOMA, 181 'xbi' => self::TAHOMA_BOLD, 182 ], 183 'Times New Roman' => [ 184 'x' => self::TIMES_NEW_ROMAN, 185 'xb' => self::TIMES_NEW_ROMAN_BOLD, 186 'xi' => self::TIMES_NEW_ROMAN_ITALIC, 187 'xbi' => self::TIMES_NEW_ROMAN_BOLD_ITALIC, 188 ], 189 'Trebuchet MS' => [ 190 'x' => self::TREBUCHET_MS, 191 'xb' => self::TREBUCHET_MS_BOLD, 192 'xi' => self::TREBUCHET_MS_ITALIC, 193 'xbi' => self::TREBUCHET_MS_BOLD_ITALIC, 194 ], 195 'Verdana' => [ 196 'x' => self::VERDANA, 197 'xb' => self::VERDANA_BOLD, 198 'xi' => self::VERDANA_ITALIC, 199 'xbi' => self::VERDANA_BOLD_ITALIC, 200 ], 201 ]; 202 203 /** 204 * AutoSize method. 205 * 206 * @var string 207 */ 208 private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX; 209 210 /** 211 * Path to folder containing TrueType font .ttf files. 212 * 213 * @var string 214 */ 215 private static $trueTypeFontPath = ''; 216 217 /** 218 * How wide is a default column for a given default font and size? 219 * Empirical data found by inspecting real Excel files and reading off the pixel width 220 * in Microsoft Office Excel 2007. 221 * Added height in points. 222 */ 223 public const DEFAULT_COLUMN_WIDTHS = [ 224 'Arial' => [ 225 1 => ['px' => 24, 'width' => 12.00000000, 'height' => 5.25], 226 2 => ['px' => 24, 'width' => 12.00000000, 'height' => 5.25], 227 3 => ['px' => 32, 'width' => 10.66406250, 'height' => 6.0], 228 229 4 => ['px' => 32, 'width' => 10.66406250, 'height' => 6.75], 230 5 => ['px' => 40, 'width' => 10.00000000, 'height' => 8.25], 231 6 => ['px' => 48, 'width' => 9.59765625, 'height' => 8.25], 232 7 => ['px' => 48, 'width' => 9.59765625, 'height' => 9.0], 233 8 => ['px' => 56, 'width' => 9.33203125, 'height' => 11.25], 234 9 => ['px' => 64, 'width' => 9.14062500, 'height' => 12.0], 235 10 => ['px' => 64, 'width' => 9.14062500, 'height' => 12.75], 236 ], 237 'Calibri' => [ 238 1 => ['px' => 24, 'width' => 12.00000000, 'height' => 5.25], 239 2 => ['px' => 24, 'width' => 12.00000000, 'height' => 5.25], 240 3 => ['px' => 32, 'width' => 10.66406250, 'height' => 6.00], 241 4 => ['px' => 32, 'width' => 10.66406250, 'height' => 6.75], 242 5 => ['px' => 40, 'width' => 10.00000000, 'height' => 8.25], 243 6 => ['px' => 48, 'width' => 9.59765625, 'height' => 8.25], 244 7 => ['px' => 48, 'width' => 9.59765625, 'height' => 9.0], 245 8 => ['px' => 56, 'width' => 9.33203125, 'height' => 11.25], 246 9 => ['px' => 56, 'width' => 9.33203125, 'height' => 12.0], 247 10 => ['px' => 64, 'width' => 9.14062500, 'height' => 12.75], 248 11 => ['px' => 64, 'width' => 9.14062500, 'height' => 15.0], 249 ], 250 'Verdana' => [ 251 1 => ['px' => 24, 'width' => 12.00000000, 'height' => 5.25], 252 2 => ['px' => 24, 'width' => 12.00000000, 'height' => 5.25], 253 3 => ['px' => 32, 'width' => 10.66406250, 'height' => 6.0], 254 4 => ['px' => 32, 'width' => 10.66406250, 'height' => 6.75], 255 5 => ['px' => 40, 'width' => 10.00000000, 'height' => 8.25], 256 6 => ['px' => 48, 'width' => 9.59765625, 'height' => 8.25], 257 7 => ['px' => 48, 'width' => 9.59765625, 'height' => 9.0], 258 8 => ['px' => 64, 'width' => 9.14062500, 'height' => 10.5], 259 9 => ['px' => 72, 'width' => 9.00000000, 'height' => 11.25], 260 10 => ['px' => 72, 'width' => 9.00000000, 'height' => 12.75], 261 ], 262 ]; 263 264 /** 265 * List of column widths. Replaced by constant; 266 * previously it was public and updateable, allowing 267 * user to make inappropriate alterations. 268 * 269 * @deprecated 1.25.0 Use DEFAULT_COLUMN_WIDTHS constant instead. 270 * 271 * @var array 272 */ 273 public static $defaultColumnWidths = self::DEFAULT_COLUMN_WIDTHS; 274 275 /** 276 * Set autoSize method. 277 * 278 * @param string $method see self::AUTOSIZE_METHOD_* 279 * 280 * @return bool Success or failure 281 */ 282 public static function setAutoSizeMethod($method) 283 { 284 if (!in_array($method, self::AUTOSIZE_METHODS)) { 285 return false; 286 } 287 self::$autoSizeMethod = $method; 288 289 return true; 290 } 291 292 /** 293 * Get autoSize method. 294 * 295 * @return string 296 */ 297 public static function getAutoSizeMethod() 298 { 299 return self::$autoSizeMethod; 300 } 301 302 /** 303 * Set the path to the folder containing .ttf files. There should be a trailing slash. 304 * Typical locations on variout some platforms: 305 * <ul> 306 * <li>C:/Windows/Fonts/</li> 307 * <li>/usr/share/fonts/truetype/</li> 308 * <li>~/.fonts/</li> 309 * </ul>. 310 * 311 * @param string $folderPath 312 */ 313 public static function setTrueTypeFontPath($folderPath): void 314 { 315 self::$trueTypeFontPath = $folderPath; 316 } 317 318 /** 319 * Get the path to the folder containing .ttf files. 320 * 321 * @return string 322 */ 323 public static function getTrueTypeFontPath() 324 { 325 return self::$trueTypeFontPath; 326 } 327 328 /** 329 * Calculate an (approximate) OpenXML column width, based on font size and text contained. 330 * 331 * @param FontStyle $font Font object 332 * @param null|RichText|string $cellText Text to calculate width 333 * @param int $rotation Rotation angle 334 * @param null|FontStyle $defaultFont Font object 335 * @param bool $filterAdjustment Add space for Autofilter or Table dropdown 336 */ 337 public static function calculateColumnWidth( 338 FontStyle $font, 339 $cellText = '', 340 $rotation = 0, 341 ?FontStyle $defaultFont = null, 342 bool $filterAdjustment = false, 343 int $indentAdjustment = 0 344 ): int { 345 // If it is rich text, use plain text 346 if ($cellText instanceof RichText) { 347 $cellText = $cellText->getPlainText(); 348 } 349 350 // Special case if there are one or more newline characters ("\n") 351 $cellText = $cellText ?? ''; 352 if (strpos(/** @scrutinizer ignore-type */ $cellText, "\n") !== false) { 353 $lineTexts = explode("\n", $cellText); 354 $lineWidths = []; 355 foreach ($lineTexts as $lineText) { 356 $lineWidths[] = self::calculateColumnWidth($font, $lineText, $rotation = 0, $defaultFont, $filterAdjustment); 357 } 358 359 return max($lineWidths); // width of longest line in cell 360 } 361 362 // Try to get the exact text width in pixels 363 $approximate = self::$autoSizeMethod === self::AUTOSIZE_METHOD_APPROX; 364 $columnWidth = 0; 365 if (!$approximate) { 366 $columnWidthAdjust = ceil( 367 self::getTextWidthPixelsExact( 368 str_repeat('n', 1 * (($filterAdjustment ? 3 : 1) + ($indentAdjustment * 2))), 369 $font, 370 0 371 ) * 1.07 372 ); 373 374 try { 375 // Width of text in pixels excl. padding 376 // and addition because Excel adds some padding, just use approx width of 'n' glyph 377 $columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation) + $columnWidthAdjust; 378 } catch (PhpSpreadsheetException $e) { 379 $approximate = true; 380 } 381 } 382 383 if ($approximate) { 384 $columnWidthAdjust = self::getTextWidthPixelsApprox( 385 str_repeat('n', 1 * (($filterAdjustment ? 3 : 1) + ($indentAdjustment * 2))), 386 $font, 387 0 388 ); 389 // Width of text in pixels excl. padding, approximation 390 // and addition because Excel adds some padding, just use approx width of 'n' glyph 391 $columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation) + $columnWidthAdjust; 392 } 393 394 // Convert from pixel width to column width 395 $columnWidth = Drawing::pixelsToCellDimension((int) $columnWidth, $defaultFont ?? new FontStyle()); 396 397 // Return 398 return (int) round($columnWidth, 6); 399 } 400 401 /** 402 * Get GD text width in pixels for a string of text in a certain font at a certain rotation angle. 403 */ 404 public static function getTextWidthPixelsExact(string $text, FontStyle $font, int $rotation = 0): int 405 { 406 if (!function_exists('imagettfbbox')) { 407 throw new PhpSpreadsheetException('GD library needs to be enabled'); 408 } 409 410 // font size should really be supplied in pixels in GD2, 411 // but since GD2 seems to assume 72dpi, pixels and points are the same 412 $fontFile = self::getTrueTypeFontFileFromFont($font); 413 $textBox = imagettfbbox($font->getSize() ?? 10.0, $rotation, $fontFile, $text); 414 if ($textBox === false) { 415 // @codeCoverageIgnoreStart 416 throw new PhpSpreadsheetException('imagettfbbox failed'); 417 // @codeCoverageIgnoreEnd 418 } 419 420 // Get corners positions 421 $lowerLeftCornerX = $textBox[0]; 422 $lowerRightCornerX = $textBox[2]; 423 $upperRightCornerX = $textBox[4]; 424 $upperLeftCornerX = $textBox[6]; 425 426 // Consider the rotation when calculating the width 427 return max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX); 428 } 429 430 /** 431 * Get approximate width in pixels for a string of text in a certain font at a certain rotation angle. 432 * 433 * @param string $columnText 434 * @param int $rotation 435 * 436 * @return int Text width in pixels (no padding added) 437 */ 438 public static function getTextWidthPixelsApprox($columnText, FontStyle $font, $rotation = 0) 439 { 440 $fontName = $font->getName(); 441 $fontSize = $font->getSize(); 442 443 // Calculate column width in pixels. We assume fixed glyph width. Result varies with font name and size. 444 switch ($fontName) { 445 case 'Calibri': 446 // value 8.26 was found via interpolation by inspecting real Excel files with Calibri 11 font. 447 $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText)); 448 $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size 449 450 break; 451 case 'Arial': 452 // value 8 was set because of experience in different exports at Arial 10 font. 453 $columnWidth = (int) (8 * StringHelper::countCharacters($columnText)); 454 $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size 455 456 break; 457 case 'Verdana': 458 // value 8 was found via interpolation by inspecting real Excel files with Verdana 10 font. 459 $columnWidth = (int) (8 * StringHelper::countCharacters($columnText)); 460 $columnWidth = $columnWidth * $fontSize / 10; // extrapolate from font size 461 462 break; 463 default: 464 // just assume Calibri 465 $columnWidth = (int) (8.26 * StringHelper::countCharacters($columnText)); 466 $columnWidth = $columnWidth * $fontSize / 11; // extrapolate from font size 467 468 break; 469 } 470 471 // Calculate approximate rotated column width 472 if ($rotation !== 0) { 473 if ($rotation == Alignment::TEXTROTATION_STACK_PHPSPREADSHEET) { 474 // stacked text 475 $columnWidth = 4; // approximation 476 } else { 477 // rotated text 478 $columnWidth = $columnWidth * cos(deg2rad($rotation)) 479 + $fontSize * abs(sin(deg2rad($rotation))) / 5; // approximation 480 } 481 } 482 483 // pixel width is an integer 484 return (int) $columnWidth; 485 } 486 487 /** 488 * Calculate an (approximate) pixel size, based on a font points size. 489 * 490 * @param int $fontSizeInPoints Font size (in points) 491 * 492 * @return int Font size (in pixels) 493 */ 494 public static function fontSizeToPixels($fontSizeInPoints) 495 { 496 return (int) ((4 / 3) * $fontSizeInPoints); 497 } 498 499 /** 500 * Calculate an (approximate) pixel size, based on inch size. 501 * 502 * @param int $sizeInInch Font size (in inch) 503 * 504 * @return int Size (in pixels) 505 */ 506 public static function inchSizeToPixels($sizeInInch) 507 { 508 return $sizeInInch * 96; 509 } 510 511 /** 512 * Calculate an (approximate) pixel size, based on centimeter size. 513 * 514 * @param int $sizeInCm Font size (in centimeters) 515 * 516 * @return float Size (in pixels) 517 */ 518 public static function centimeterSizeToPixels($sizeInCm) 519 { 520 return $sizeInCm * 37.795275591; 521 } 522 523 /** 524 * Returns the font path given the font. 525 * 526 * @return string Path to TrueType font file 527 */ 528 public static function getTrueTypeFontFileFromFont(FontStyle $font, bool $checkPath = true) 529 { 530 if ($checkPath && (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath))) { 531 throw new PhpSpreadsheetException('Valid directory to TrueType Font files not specified'); 532 } 533 534 $name = $font->getName(); 535 if (!isset(self::FONT_FILE_NAMES[$name])) { 536 throw new PhpSpreadsheetException('Unknown font name "' . $name . '". Cannot map to TrueType font file'); 537 } 538 $bold = $font->getBold(); 539 $italic = $font->getItalic(); 540 $index = 'x'; 541 if ($bold) { 542 $index .= 'b'; 543 } 544 if ($italic) { 545 $index .= 'i'; 546 } 547 $fontFile = self::FONT_FILE_NAMES[$name][$index]; 548 549 $separator = ''; 550 if (mb_strlen(self::$trueTypeFontPath) > 1 && mb_substr(self::$trueTypeFontPath, -1) !== '/' && mb_substr(self::$trueTypeFontPath, -1) !== '\\') { 551 $separator = DIRECTORY_SEPARATOR; 552 } 553 $fontFile = self::$trueTypeFontPath . $separator . $fontFile; 554 555 // Check if file actually exists 556 if ($checkPath && !file_exists($fontFile)) { 557 throw new PhpSpreadsheetException('TrueType Font file not found'); 558 } 559 560 return $fontFile; 561 } 562 563 public const CHARSET_FROM_FONT_NAME = [ 564 'EucrosiaUPC' => self::CHARSET_ANSI_THAI, 565 'Wingdings' => self::CHARSET_SYMBOL, 566 'Wingdings 2' => self::CHARSET_SYMBOL, 567 'Wingdings 3' => self::CHARSET_SYMBOL, 568 ]; 569 570 /** 571 * Returns the associated charset for the font name. 572 * 573 * @param string $fontName Font name 574 * 575 * @return int Character set code 576 */ 577 public static function getCharsetFromFontName($fontName) 578 { 579 return self::CHARSET_FROM_FONT_NAME[$fontName] ?? self::CHARSET_ANSI_LATIN; 580 } 581 582 /** 583 * Get the effective column width for columns without a column dimension or column with width -1 584 * For example, for Calibri 11 this is 9.140625 (64 px). 585 * 586 * @param FontStyle $font The workbooks default font 587 * @param bool $returnAsPixels true = return column width in pixels, false = return in OOXML units 588 * 589 * @return mixed Column width 590 */ 591 public static function getDefaultColumnWidthByFont(FontStyle $font, $returnAsPixels = false) 592 { 593 if (isset(self::DEFAULT_COLUMN_WIDTHS[$font->getName()][$font->getSize()])) { 594 // Exact width can be determined 595 $columnWidth = $returnAsPixels ? 596 self::DEFAULT_COLUMN_WIDTHS[$font->getName()][$font->getSize()]['px'] 597 : self::DEFAULT_COLUMN_WIDTHS[$font->getName()][$font->getSize()]['width']; 598 } else { 599 // We don't have data for this particular font and size, use approximation by 600 // extrapolating from Calibri 11 601 $columnWidth = $returnAsPixels ? 602 self::DEFAULT_COLUMN_WIDTHS['Calibri'][11]['px'] 603 : self::DEFAULT_COLUMN_WIDTHS['Calibri'][11]['width']; 604 $columnWidth = $columnWidth * $font->getSize() / 11; 605 606 // Round pixels to closest integer 607 if ($returnAsPixels) { 608 $columnWidth = (int) round($columnWidth); 609 } 610 } 611 612 return $columnWidth; 613 } 614 615 /** 616 * Get the effective row height for rows without a row dimension or rows with height -1 617 * For example, for Calibri 11 this is 15 points. 618 * 619 * @param FontStyle $font The workbooks default font 620 * 621 * @return float Row height in points 622 */ 623 public static function getDefaultRowHeightByFont(FontStyle $font) 624 { 625 $name = $font->getName(); 626 $size = $font->getSize(); 627 if (isset(self::DEFAULT_COLUMN_WIDTHS[$name][$size])) { 628 $rowHeight = self::DEFAULT_COLUMN_WIDTHS[$name][$size]['height']; 629 } elseif ($name === 'Arial' || $name === 'Verdana') { 630 $rowHeight = self::DEFAULT_COLUMN_WIDTHS[$name][10]['height'] * $size / 10.0; 631 } else { 632 $rowHeight = self::DEFAULT_COLUMN_WIDTHS['Calibri'][11]['height'] * $size / 11.0; 633 } 634 635 return $rowHeight; 636 } 637 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body