1<?php
2
3namespace PhpOffice\PhpSpreadsheet\Writer\Xls;
4
5use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
6
7class Font
8{
9    /**
10     * Color index.
11     *
12     * @var int
13     */
14    private $colorIndex;
15
16    /**
17     * Font.
18     *
19     * @var \PhpOffice\PhpSpreadsheet\Style\Font
20     */
21    private $font;
22
23    /**
24     * Constructor.
25     *
26     * @param \PhpOffice\PhpSpreadsheet\Style\Font $font
27     */
28    public function __construct(\PhpOffice\PhpSpreadsheet\Style\Font $font)
29    {
30        $this->colorIndex = 0x7FFF;
31        $this->font = $font;
32    }
33
34    /**
35     * Set the color index.
36     *
37     * @param int $colorIndex
38     */
39    public function setColorIndex($colorIndex)
40    {
41        $this->colorIndex = $colorIndex;
42    }
43
44    /**
45     * Get font record data.
46     *
47     * @return string
48     */
49    public function writeFont()
50    {
51        $font_outline = 0;
52        $font_shadow = 0;
53
54        $icv = $this->colorIndex; // Index to color palette
55        if ($this->font->getSuperscript()) {
56            $sss = 1;
57        } elseif ($this->font->getSubscript()) {
58            $sss = 2;
59        } else {
60            $sss = 0;
61        }
62        $bFamily = 0; // Font family
63        $bCharSet = \PhpOffice\PhpSpreadsheet\Shared\Font::getCharsetFromFontName($this->font->getName()); // Character set
64
65        $record = 0x31; // Record identifier
66        $reserved = 0x00; // Reserved
67        $grbit = 0x00; // Font attributes
68        if ($this->font->getItalic()) {
69            $grbit |= 0x02;
70        }
71        if ($this->font->getStrikethrough()) {
72            $grbit |= 0x08;
73        }
74        if ($font_outline) {
75            $grbit |= 0x10;
76        }
77        if ($font_shadow) {
78            $grbit |= 0x20;
79        }
80
81        $data = pack(
82            'vvvvvCCCC',
83            // Fontsize (in twips)
84            $this->font->getSize() * 20,
85            $grbit,
86            // Colour
87            $icv,
88            // Font weight
89            self::mapBold($this->font->getBold()),
90            // Superscript/Subscript
91            $sss,
92            self::mapUnderline($this->font->getUnderline()),
93            $bFamily,
94            $bCharSet,
95            $reserved
96        );
97        $data .= StringHelper::UTF8toBIFF8UnicodeShort($this->font->getName());
98
99        $length = strlen($data);
100        $header = pack('vv', $record, $length);
101
102        return $header . $data;
103    }
104
105    /**
106     * Map to BIFF5-BIFF8 codes for bold.
107     *
108     * @param bool $bold
109     *
110     * @return int
111     */
112    private static function mapBold($bold)
113    {
114        if ($bold) {
115            return 0x2BC; //  700 = Bold font weight
116        }
117
118        return 0x190; //  400 = Normal font weight
119    }
120
121    /**
122     * Map of BIFF2-BIFF8 codes for underline styles.
123     *
124     * @var array of int
125     */
126    private static $mapUnderline = [
127        \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_NONE => 0x00,
128        \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLE => 0x01,
129        \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLE => 0x02,
130        \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_SINGLEACCOUNTING => 0x21,
131        \PhpOffice\PhpSpreadsheet\Style\Font::UNDERLINE_DOUBLEACCOUNTING => 0x22,
132    ];
133
134    /**
135     * Map underline.
136     *
137     * @param string $underline
138     *
139     * @return int
140     */
141    private static function mapUnderline($underline)
142    {
143        if (isset(self::$mapUnderline[$underline])) {
144            return self::$mapUnderline[$underline];
145        }
146
147        return 0x00;
148    }
149}
150