Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.44% covered (success)
98.44%
63 / 64
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
Font
98.44% covered (success)
98.44%
63 / 64
50.00% covered (danger)
50.00%
1 / 2
18
0.00% covered (danger)
0.00%
0 / 1
 write
100.00% covered (success)
100.00%
51 / 51
100.00% covered (success)
100.00%
1 / 1
5
 writeLanguage
92.31% covered (success)
92.31%
12 / 13
0.00% covered (danger)
0.00%
0 / 1
13.08
1<?php
2
3/**
4 * This file is part of PHPWord - A pure PHP library for reading and writing
5 * word processing documents.
6 *
7 * PHPWord is free software distributed under the terms of the GNU Lesser
8 * General Public License version 3 as published by the Free Software Foundation.
9 *
10 * For the full copyright and license information, please read the LICENSE
11 * file that was distributed with this source code. For the full list of
12 * contributors, visit https://github.com/PHPOffice/PHPWord/contributors.
13 *
14 * @see         https://github.com/PHPOffice/PHPWord
15 *
16 * @license     http://www.gnu.org/licenses/lgpl.txt LGPL version 3
17 */
18
19namespace PhpOffice\PhpWord\Writer\ODText\Style;
20
21use PhpOffice\PhpWord\Shared\XMLWriter;
22use PhpOffice\PhpWord\Style\Language;
23
24/**
25 * Font style writer.
26 *
27 * @since 0.10.0
28 */
29class Font extends AbstractStyle
30{
31    /**
32     * Write style.
33     */
34    public function write(): void
35    {
36        $style = $this->getStyle();
37        if (!$style instanceof \PhpOffice\PhpWord\Style\Font) {
38            return;
39        }
40        $xmlWriter = $this->getXmlWriter();
41
42        $stylep = $style->getParagraph();
43        if ($stylep instanceof \PhpOffice\PhpWord\Style\Paragraph) {
44            $temp1 = clone $stylep;
45            $temp1->setStyleName($style->getStyleName());
46            $temp2 = new Paragraph($xmlWriter, $temp1);
47            $temp2->write();
48        }
49
50        $xmlWriter->startElement('style:style');
51        $xmlWriter->writeAttribute('style:name', $style->getStyleName());
52        $xmlWriter->writeAttribute('style:family', 'text');
53        $xmlWriter->startElement('style:text-properties');
54
55        // Name
56        $font = $style->getName();
57        $xmlWriter->writeAttributeIf($font != '', 'style:font-name', $font);
58        $xmlWriter->writeAttributeIf($font != '', 'style:font-name-complex', $font);
59        $size = $style->getSize();
60
61        // Size
62        $xmlWriter->writeAttributeIf(is_numeric($size), 'fo:font-size', $size . 'pt');
63        $xmlWriter->writeAttributeIf(is_numeric($size), 'style:font-size-asian', $size . 'pt');
64        $xmlWriter->writeAttributeIf(is_numeric($size), 'style:font-size-complex', $size . 'pt');
65
66        // Color
67        $color = $style->getColor();
68        $xmlWriter->writeAttributeIf($color != '', 'fo:color', '#' . \PhpOffice\PhpWord\Shared\Converter::stringToRgb($color));
69
70        // Bold & italic
71        $xmlWriter->writeAttributeIf($style->isBold(), 'fo:font-weight', 'bold');
72        $xmlWriter->writeAttributeIf($style->isBold(), 'style:font-weight-asian', 'bold');
73        $xmlWriter->writeAttributeIf($style->isItalic(), 'fo:font-style', 'italic');
74        $xmlWriter->writeAttributeIf($style->isItalic(), 'style:font-style-asian', 'italic');
75        $xmlWriter->writeAttributeIf($style->isItalic(), 'style:font-style-complex', 'italic');
76
77        // Underline
78        // @todo Various mode of underline
79        $underline = $style->getUnderline();
80        $xmlWriter->writeAttributeIf($underline != 'none', 'style:text-underline-style', 'solid');
81
82        // Strikethrough, double strikethrough
83        $xmlWriter->writeAttributeIf($style->isStrikethrough(), 'style:text-line-through-type', 'single');
84        $xmlWriter->writeAttributeIf($style->isDoubleStrikethrough(), 'style:text-line-through-type', 'double');
85
86        // Small caps, all caps
87        $xmlWriter->writeAttributeIf($style->isSmallCaps(), 'fo:font-variant', 'small-caps');
88        $xmlWriter->writeAttributeIf($style->isAllCaps(), 'fo:text-transform', 'uppercase');
89
90        //Hidden text
91        $xmlWriter->writeAttributeIf($style->isHidden(), 'text:display', 'none');
92
93        // Superscript/subscript
94        $xmlWriter->writeAttributeIf($style->isSuperScript(), 'style:text-position', 'super');
95        $xmlWriter->writeAttributeIf($style->isSubScript(), 'style:text-position', 'sub');
96
97        $language = $style->getLang();
98        if ($style->isNoProof()) {
99            $xmlWriter->writeAttribute('fo:language', 'zxx');
100            $xmlWriter->writeAttribute('style:language-asian', 'zxx');
101            $xmlWriter->writeAttribute('style:language-complex', 'zxx');
102            $xmlWriter->writeAttribute('fo:country', 'none');
103            $xmlWriter->writeAttribute('style:country-asian', 'none');
104            $xmlWriter->writeAttribute('style:country-complex', 'none');
105        } elseif ($language instanceof Language) {
106            self::writeLanguage($xmlWriter, $language->getLatin());
107            self::writeLanguage($xmlWriter, $language->getEastAsia(), 'asian');
108            self::writeLanguage($xmlWriter, $language->getBidirectional(), 'complex');
109        }
110
111        // @todo Foreground-Color
112
113        // @todo Background color
114
115        $xmlWriter->endElement(); // style:text-properties
116        $xmlWriter->endElement(); // style:style
117    }
118
119    /**
120     * Write a BCP 47 language tag, such as uk-UA or sr-Latn-RS, as the language, script and country of ODF.
121     *
122     * @param string $script '' for Western text, 'asian' or 'complex'
123     */
124    public static function writeLanguage(XMLWriter $xmlWriter, ?string $tag, string $script = ''): void
125    {
126        if ($tag === null || $tag === '') {
127            return;
128        }
129        $subtags = explode('-', $tag);
130        $language = array_shift($subtags);
131        // Not a language, such as x-none, which Word writes for no language
132        if (!preg_match('/^[A-Za-z]{2,3}$/', $language)) {
133            return;
134        }
135        $scriptCode = isset($subtags[0]) && preg_match('/^[A-Za-z]{4}$/', $subtags[0]) ? array_shift($subtags) : null;
136        $country = isset($subtags[0]) && preg_match('/^([A-Za-z]{2}|\\d{3})$/', $subtags[0]) ? array_shift($subtags) : null;
137        $suffix = $script === '' ? '' : '-' . $script;
138        $xmlWriter->writeAttribute($script === '' ? 'fo:language' : 'style:language' . $suffix, $language);
139        $xmlWriter->writeAttributeIf($scriptCode !== null, $script === '' ? 'fo:script' : 'style:script' . $suffix, (string) $scriptCode);
140        $xmlWriter->writeAttributeIf($country !== null, $script === '' ? 'fo:country' : 'style:country' . $suffix, (string) $country);
141        // As LibreOffice writes it: the whole tag when it has a script, a variant or an extension
142        $xmlWriter->writeAttributeIf($scriptCode !== null || count($subtags) > 0, 'style:rfc-language-tag' . $suffix, $tag);
143    }
144}