1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
27:
28:
29: 30: 31: 32: 33: 34: 35:
36: class PHPExcel_Shared_Font
37: {
38:
39: const AUTOSIZE_METHOD_APPROX = 'approx';
40: const AUTOSIZE_METHOD_EXACT = 'exact';
41:
42: private static $_autoSizeMethods = array(
43: self::AUTOSIZE_METHOD_APPROX,
44: self::AUTOSIZE_METHOD_EXACT,
45: );
46:
47:
48: const CHARSET_ANSI_LATIN = 0x00;
49: const CHARSET_SYSTEM_DEFAULT = 0x01;
50: const CHARSET_SYMBOL = 0x02;
51: const CHARSET_APPLE_ROMAN = 0x4D;
52: const CHARSET_ANSI_JAPANESE_SHIFTJIS = 0x80;
53: const CHARSET_ANSI_KOREAN_HANGUL = 0x81;
54: const CHARSET_ANSI_KOREAN_JOHAB = 0x82;
55: const CHARSET_ANSI_CHINESE_SIMIPLIFIED = 0x86;
56: const CHARSET_ANSI_CHINESE_TRADITIONAL = 0x88;
57: const CHARSET_ANSI_GREEK = 0xA1;
58: const CHARSET_ANSI_TURKISH = 0xA2;
59: const CHARSET_ANSI_VIETNAMESE = 0xA3;
60: const CHARSET_ANSI_HEBREW = 0xB1;
61: const CHARSET_ANSI_ARABIC = 0xB2;
62: const CHARSET_ANSI_BALTIC = 0xBA;
63: const CHARSET_ANSI_CYRILLIC = 0xCC;
64: const CHARSET_ANSI_THAI = 0xDD;
65: const CHARSET_ANSI_LATIN_II = 0xEE;
66: const CHARSET_OEM_LATIN_I = 0xFF;
67:
68:
69:
70: const ARIAL = 'arial.ttf';
71: const ARIAL_BOLD = 'arialbd.ttf';
72: const ARIAL_ITALIC = 'ariali.ttf';
73: const ARIAL_BOLD_ITALIC = 'arialbi.ttf';
74:
75: const CALIBRI = 'CALIBRI.TTF';
76: const CALIBRI_BOLD = 'CALIBRIB.TTF';
77: const CALIBRI_ITALIC = 'CALIBRII.TTF';
78: const CALIBRI_BOLD_ITALIC = 'CALIBRIZ.TTF';
79:
80: const COMIC_SANS_MS = 'comic.ttf';
81: const COMIC_SANS_MS_BOLD = 'comicbd.ttf';
82:
83: const COURIER_NEW = 'cour.ttf';
84: const COURIER_NEW_BOLD = 'courbd.ttf';
85: const COURIER_NEW_ITALIC = 'couri.ttf';
86: const COURIER_NEW_BOLD_ITALIC = 'courbi.ttf';
87:
88: const GEORGIA = 'georgia.ttf';
89: const GEORGIA_BOLD = 'georgiab.ttf';
90: const GEORGIA_ITALIC = 'georgiai.ttf';
91: const GEORGIA_BOLD_ITALIC = 'georgiaz.ttf';
92:
93: const IMPACT = 'impact.ttf';
94:
95: const LIBERATION_SANS = 'LiberationSans-Regular.ttf';
96: const LIBERATION_SANS_BOLD = 'LiberationSans-Bold.ttf';
97: const LIBERATION_SANS_ITALIC = 'LiberationSans-Italic.ttf';
98: const LIBERATION_SANS_BOLD_ITALIC = 'LiberationSans-BoldItalic.ttf';
99:
100: const LUCIDA_CONSOLE = 'lucon.ttf';
101: const LUCIDA_SANS_UNICODE = 'l_10646.ttf';
102:
103: const MICROSOFT_SANS_SERIF = 'micross.ttf';
104:
105: const PALATINO_LINOTYPE = 'pala.ttf';
106: const PALATINO_LINOTYPE_BOLD = 'palab.ttf';
107: const PALATINO_LINOTYPE_ITALIC = 'palai.ttf';
108: const PALATINO_LINOTYPE_BOLD_ITALIC = 'palabi.ttf';
109:
110: const SYMBOL = 'symbol.ttf';
111:
112: const TAHOMA = 'tahoma.ttf';
113: const TAHOMA_BOLD = 'tahomabd.ttf';
114:
115: const TIMES_NEW_ROMAN = 'times.ttf';
116: const TIMES_NEW_ROMAN_BOLD = 'timesbd.ttf';
117: const TIMES_NEW_ROMAN_ITALIC = 'timesi.ttf';
118: const TIMES_NEW_ROMAN_BOLD_ITALIC = 'timesbi.ttf';
119:
120: const TREBUCHET_MS = 'trebuc.ttf';
121: const TREBUCHET_MS_BOLD = 'trebucbd.ttf';
122: const TREBUCHET_MS_ITALIC = 'trebucit.ttf';
123: const TREBUCHET_MS_BOLD_ITALIC = 'trebucbi.ttf';
124:
125: const VERDANA = 'verdana.ttf';
126: const VERDANA_BOLD = 'verdanab.ttf';
127: const VERDANA_ITALIC = 'verdanai.ttf';
128: const VERDANA_BOLD_ITALIC = 'verdanaz.ttf';
129:
130: 131: 132: 133: 134:
135: private static $autoSizeMethod = self::AUTOSIZE_METHOD_APPROX;
136:
137: 138: 139: 140: 141:
142: private static $trueTypeFontPath = null;
143:
144: 145: 146: 147: 148: 149: 150:
151: public static $defaultColumnWidths = array(
152: 'Arial' => array(
153: 1 => array('px' => 24, 'width' => 12.00000000),
154: 2 => array('px' => 24, 'width' => 12.00000000),
155: 3 => array('px' => 32, 'width' => 10.66406250),
156: 4 => array('px' => 32, 'width' => 10.66406250),
157: 5 => array('px' => 40, 'width' => 10.00000000),
158: 6 => array('px' => 48, 'width' => 9.59765625),
159: 7 => array('px' => 48, 'width' => 9.59765625),
160: 8 => array('px' => 56, 'width' => 9.33203125),
161: 9 => array('px' => 64, 'width' => 9.14062500),
162: 10 => array('px' => 64, 'width' => 9.14062500),
163: ),
164: 'Calibri' => array(
165: 1 => array('px' => 24, 'width' => 12.00000000),
166: 2 => array('px' => 24, 'width' => 12.00000000),
167: 3 => array('px' => 32, 'width' => 10.66406250),
168: 4 => array('px' => 32, 'width' => 10.66406250),
169: 5 => array('px' => 40, 'width' => 10.00000000),
170: 6 => array('px' => 48, 'width' => 9.59765625),
171: 7 => array('px' => 48, 'width' => 9.59765625),
172: 8 => array('px' => 56, 'width' => 9.33203125),
173: 9 => array('px' => 56, 'width' => 9.33203125),
174: 10 => array('px' => 64, 'width' => 9.14062500),
175: 11 => array('px' => 64, 'width' => 9.14062500),
176: ),
177: 'Verdana' => array(
178: 1 => array('px' => 24, 'width' => 12.00000000),
179: 2 => array('px' => 24, 'width' => 12.00000000),
180: 3 => array('px' => 32, 'width' => 10.66406250),
181: 4 => array('px' => 32, 'width' => 10.66406250),
182: 5 => array('px' => 40, 'width' => 10.00000000),
183: 6 => array('px' => 48, 'width' => 9.59765625),
184: 7 => array('px' => 48, 'width' => 9.59765625),
185: 8 => array('px' => 64, 'width' => 9.14062500),
186: 9 => array('px' => 72, 'width' => 9.00000000),
187: 10 => array('px' => 72, 'width' => 9.00000000),
188: ),
189: );
190:
191: 192: 193: 194: 195: 196:
197: public static function setAutoSizeMethod($pValue = self::AUTOSIZE_METHOD_APPROX)
198: {
199: if (!in_array($pValue,self::$_autoSizeMethods)) {
200: return FALSE;
201: }
202:
203: self::$autoSizeMethod = $pValue;
204:
205: return TRUE;
206: }
207:
208: 209: 210: 211: 212:
213: public static function getAutoSizeMethod()
214: {
215: return self::$autoSizeMethod;
216: }
217:
218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228:
229: public static function setTrueTypeFontPath($pValue = '')
230: {
231: self::$trueTypeFontPath = $pValue;
232: }
233:
234: 235: 236: 237: 238:
239: public static function getTrueTypeFontPath()
240: {
241: return self::$trueTypeFontPath;
242: }
243:
244: 245: 246: 247: 248: 249: 250: 251: 252:
253: public static function calculateColumnWidth(PHPExcel_Style_Font $font, $cellText = '', $rotation = 0, PHPExcel_Style_Font $defaultFont = null) {
254:
255:
256: if ($cellText instanceof PHPExcel_RichText) {
257: $cellText = $cellText->getPlainText();
258: }
259:
260:
261: if (strpos($cellText, "\n") !== false) {
262: $lineTexts = explode("\n", $cellText);
263: $lineWitdhs = array();
264: foreach ($lineTexts as $lineText) {
265: $lineWidths[] = self::calculateColumnWidth($font, $lineText, $rotation = 0, $defaultFont);
266: }
267: return max($lineWidths);
268: }
269:
270:
271: try {
272:
273: if (self::$autoSizeMethod == self::AUTOSIZE_METHOD_APPROX) {
274: throw new PHPExcel_Exception('AutoSize method is set to approx');
275: }
276:
277:
278: $columnWidth = self::getTextWidthPixelsExact($cellText, $font, $rotation);
279:
280:
281: $columnWidth += ceil(self::getTextWidthPixelsExact('0', $font, 0) * 1.07);
282:
283: } catch (PHPExcel_Exception $e) {
284:
285: $columnWidth = self::getTextWidthPixelsApprox($cellText, $font, $rotation);
286:
287:
288: $columnWidth += self::getTextWidthPixelsApprox('n', $font, 0);
289: }
290:
291:
292: $columnWidth = PHPExcel_Shared_Drawing::pixelsToCellDimension($columnWidth, $defaultFont);
293:
294:
295: return round($columnWidth, 6);
296: }
297:
298: 299: 300: 301: 302: 303: 304: 305: 306:
307: public static function getTextWidthPixelsExact($text, PHPExcel_Style_Font $font, $rotation = 0) {
308: if (!function_exists('imagettfbbox')) {
309: throw new PHPExcel_Exception('GD library needs to be enabled');
310: }
311:
312:
313:
314: $fontFile = self::getTrueTypeFontFileFromFont($font);
315: $textBox = imagettfbbox($font->getSize(), $rotation, $fontFile, $text);
316:
317:
318: $lowerLeftCornerX = $textBox[0];
319: $lowerLeftCornerY = $textBox[1];
320: $lowerRightCornerX = $textBox[2];
321: $lowerRightCornerY = $textBox[3];
322: $upperRightCornerX = $textBox[4];
323: $upperRightCornerY = $textBox[5];
324: $upperLeftCornerX = $textBox[6];
325: $upperLeftCornerY = $textBox[7];
326:
327:
328: $textWidth = max($lowerRightCornerX - $upperLeftCornerX, $upperRightCornerX - $lowerLeftCornerX);
329:
330: return $textWidth;
331: }
332:
333: 334: 335: 336: 337: 338: 339: 340:
341: public static function getTextWidthPixelsApprox($columnText, PHPExcel_Style_Font $font = null, $rotation = 0)
342: {
343: $fontName = $font->getName();
344: $fontSize = $font->getSize();
345:
346:
347: switch ($fontName) {
348: case 'Calibri':
349:
350: $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText));
351: $columnWidth = $columnWidth * $fontSize / 11;
352: break;
353:
354: case 'Arial':
355:
356: $columnWidth = (int) (7 * PHPExcel_Shared_String::CountCharacters($columnText));
357: $columnWidth = $columnWidth * $fontSize / 10;
358: break;
359:
360: case 'Verdana':
361:
362: $columnWidth = (int) (8 * PHPExcel_Shared_String::CountCharacters($columnText));
363: $columnWidth = $columnWidth * $fontSize / 10;
364: break;
365:
366: default:
367:
368: $columnWidth = (int) (8.26 * PHPExcel_Shared_String::CountCharacters($columnText));
369: $columnWidth = $columnWidth * $fontSize / 11;
370: break;
371: }
372:
373:
374: if ($rotation !== 0) {
375: if ($rotation == -165) {
376:
377: $columnWidth = 4;
378: } else {
379:
380: $columnWidth = $columnWidth * cos(deg2rad($rotation))
381: + $fontSize * abs(sin(deg2rad($rotation))) / 5;
382: }
383: }
384:
385:
386: $columnWidth = (int) $columnWidth;
387: return $columnWidth;
388: }
389:
390: 391: 392: 393: 394: 395:
396: public static function fontSizeToPixels($fontSizeInPoints = 11) {
397: return (int) ((4 / 3) * $fontSizeInPoints);
398: }
399:
400: 401: 402: 403: 404: 405:
406: public static function inchSizeToPixels($sizeInInch = 1) {
407: return ($sizeInInch * 96);
408: }
409:
410: 411: 412: 413: 414: 415:
416: public static function centimeterSizeToPixels($sizeInCm = 1) {
417: return ($sizeInCm * 37.795275591);
418: }
419:
420: 421: 422: 423: 424: 425:
426: public static function getTrueTypeFontFileFromFont($font) {
427: if (!file_exists(self::$trueTypeFontPath) || !is_dir(self::$trueTypeFontPath)) {
428: throw new PHPExcel_Exception('Valid directory to TrueType Font files not specified');
429: }
430:
431: $name = $font->getName();
432: $bold = $font->getBold();
433: $italic = $font->getItalic();
434:
435:
436: switch ($name) {
437: case 'Arial':
438: $fontFile = (
439: $bold ? ($italic ? self::ARIAL_BOLD_ITALIC : self::ARIAL_BOLD)
440: : ($italic ? self::ARIAL_ITALIC : self::ARIAL)
441: );
442: break;
443:
444: case 'Calibri':
445: $fontFile = (
446: $bold ? ($italic ? self::CALIBRI_BOLD_ITALIC : self::CALIBRI_BOLD)
447: : ($italic ? self::CALIBRI_ITALIC : self::CALIBRI)
448: );
449: break;
450:
451: case 'Courier New':
452: $fontFile = (
453: $bold ? ($italic ? self::COURIER_NEW_BOLD_ITALIC : self::COURIER_NEW_BOLD)
454: : ($italic ? self::COURIER_NEW_ITALIC : self::COURIER_NEW)
455: );
456: break;
457:
458: case 'Comic Sans MS':
459: $fontFile = (
460: $bold ? self::COMIC_SANS_MS_BOLD : self::COMIC_SANS_MS
461: );
462: break;
463:
464: case 'Georgia':
465: $fontFile = (
466: $bold ? ($italic ? self::GEORGIA_BOLD_ITALIC : self::GEORGIA_BOLD)
467: : ($italic ? self::GEORGIA_ITALIC : self::GEORGIA)
468: );
469: break;
470:
471: case 'Impact':
472: $fontFile = self::IMPACT;
473: break;
474:
475: case 'Liberation Sans':
476: $fontFile = (
477: $bold ? ($italic ? self::LIBERATION_SANS_BOLD_ITALIC : self::LIBERATION_SANS_BOLD)
478: : ($italic ? self::LIBERATION_SANS_ITALIC : self::LIBERATION_SANS)
479: );
480: break;
481:
482: case 'Lucida Console':
483: $fontFile = self::LUCIDA_CONSOLE;
484: break;
485:
486: case 'Lucida Sans Unicode':
487: $fontFile = self::LUCIDA_SANS_UNICODE;
488: break;
489:
490: case 'Microsoft Sans Serif':
491: $fontFile = self::MICROSOFT_SANS_SERIF;
492: break;
493:
494: case 'Palatino Linotype':
495: $fontFile = (
496: $bold ? ($italic ? self::PALATINO_LINOTYPE_BOLD_ITALIC : self::PALATINO_LINOTYPE_BOLD)
497: : ($italic ? self::PALATINO_LINOTYPE_ITALIC : self::PALATINO_LINOTYPE)
498: );
499: break;
500:
501: case 'Symbol':
502: $fontFile = self::SYMBOL;
503: break;
504:
505: case 'Tahoma':
506: $fontFile = (
507: $bold ? self::TAHOMA_BOLD : self::TAHOMA
508: );
509: break;
510:
511: case 'Times New Roman':
512: $fontFile = (
513: $bold ? ($italic ? self::TIMES_NEW_ROMAN_BOLD_ITALIC : self::TIMES_NEW_ROMAN_BOLD)
514: : ($italic ? self::TIMES_NEW_ROMAN_ITALIC : self::TIMES_NEW_ROMAN)
515: );
516: break;
517:
518: case 'Trebuchet MS':
519: $fontFile = (
520: $bold ? ($italic ? self::TREBUCHET_MS_BOLD_ITALIC : self::TREBUCHET_MS_BOLD)
521: : ($italic ? self::TREBUCHET_MS_ITALIC : self::TREBUCHET_MS)
522: );
523: break;
524:
525: case 'Verdana':
526: $fontFile = (
527: $bold ? ($italic ? self::VERDANA_BOLD_ITALIC : self::VERDANA_BOLD)
528: : ($italic ? self::VERDANA_ITALIC : self::VERDANA)
529: );
530: break;
531:
532: default:
533: throw new PHPExcel_Exception('Unknown font name "'. $name .'". Cannot map to TrueType font file');
534: break;
535: }
536:
537: $fontFile = self::$trueTypeFontPath . $fontFile;
538:
539:
540: if (!file_exists($fontFile)) {
541: throw New PHPExcel_Exception('TrueType Font file not found');
542: }
543:
544: return $fontFile;
545: }
546:
547: 548: 549: 550: 551: 552:
553: public static function getCharsetFromFontName($name)
554: {
555: switch ($name) {
556:
557: case 'EucrosiaUPC': return self::CHARSET_ANSI_THAI;
558: case 'Wingdings': return self::CHARSET_SYMBOL;
559: case 'Wingdings 2': return self::CHARSET_SYMBOL;
560: case 'Wingdings 3': return self::CHARSET_SYMBOL;
561: default: return self::CHARSET_ANSI_LATIN;
562: }
563: }
564:
565: 566: 567: 568: 569: 570: 571: 572:
573: public static function getDefaultColumnWidthByFont(PHPExcel_Style_Font $font, $pPixels = false)
574: {
575: if (isset(self::$defaultColumnWidths[$font->getName()][$font->getSize()])) {
576:
577: $columnWidth = $pPixels ?
578: self::$defaultColumnWidths[$font->getName()][$font->getSize()]['px']
579: : self::$defaultColumnWidths[$font->getName()][$font->getSize()]['width'];
580:
581: } else {
582:
583:
584: $columnWidth = $pPixels ?
585: self::$defaultColumnWidths['Calibri'][11]['px']
586: : self::$defaultColumnWidths['Calibri'][11]['width'];
587: $columnWidth = $columnWidth * $font->getSize() / 11;
588:
589:
590: if ($pPixels) {
591: $columnWidth = (int) round($columnWidth);
592: }
593: }
594:
595: return $columnWidth;
596: }
597:
598: 599: 600: 601: 602: 603: 604:
605: public static function getDefaultRowHeightByFont(PHPExcel_Style_Font $font)
606: {
607: switch ($font->getName()) {
608: case 'Arial':
609: switch ($font->getSize()) {
610: case 10:
611:
612: $rowHeight = 12.75;
613: break;
614:
615: case 9:
616:
617: $rowHeight = 12;
618: break;
619:
620: case 8:
621:
622: $rowHeight = 11.25;
623: break;
624:
625: case 7:
626:
627: $rowHeight = 9;
628: break;
629:
630: case 6:
631: case 5:
632:
633: $rowHeight = 8.25;
634: break;
635:
636: case 4:
637:
638: $rowHeight = 6.75;
639: break;
640:
641: case 3:
642:
643: $rowHeight = 6;
644: break;
645:
646: case 2:
647: case 1:
648:
649: $rowHeight = 5.25;
650: break;
651:
652: default:
653:
654: $rowHeight = 12.75 * $font->getSize() / 10;
655: break;
656: }
657: break;
658:
659: case 'Calibri':
660: switch ($font->getSize()) {
661: case 11:
662:
663: $rowHeight = 15;
664: break;
665:
666: case 10:
667:
668: $rowHeight = 12.75;
669: break;
670:
671: case 9:
672:
673: $rowHeight = 12;
674: break;
675:
676: case 8:
677:
678: $rowHeight = 11.25;
679: break;
680:
681: case 7:
682:
683: $rowHeight = 9;
684: break;
685:
686: case 6:
687: case 5:
688:
689: $rowHeight = 8.25;
690: break;
691:
692: case 4:
693:
694: $rowHeight = 6.75;
695: break;
696:
697: case 3:
698:
699: $rowHeight = 6.00;
700: break;
701:
702: case 2:
703: case 1:
704:
705: $rowHeight = 5.25;
706: break;
707:
708: default:
709:
710: $rowHeight = 15 * $font->getSize() / 11;
711: break;
712: }
713: break;
714:
715: case 'Verdana':
716: switch ($font->getSize()) {
717: case 10:
718:
719: $rowHeight = 12.75;
720: break;
721:
722: case 9:
723:
724: $rowHeight = 11.25;
725: break;
726:
727: case 8:
728:
729: $rowHeight = 10.50;
730: break;
731:
732: case 7:
733:
734: $rowHeight = 9.00;
735: break;
736:
737: case 6:
738: case 5:
739:
740: $rowHeight = 8.25;
741: break;
742:
743: case 4:
744:
745: $rowHeight = 6.75;
746: break;
747:
748: case 3:
749:
750: $rowHeight = 6;
751: break;
752:
753: case 2:
754: case 1:
755:
756: $rowHeight = 5.25;
757: break;
758:
759: default:
760:
761: $rowHeight = 12.75 * $font->getSize() / 10;
762: break;
763: }
764: break;
765:
766: default:
767:
768: $rowHeight = 15 * $font->getSize() / 11;
769: break;
770: }
771:
772: return $rowHeight;
773: }
774:
775: }
776: