diff --git a/docs/changes/1.x/1.5.0.md b/docs/changes/1.x/1.5.0.md index b96865bada..bd93884d52 100644 --- a/docs/changes/1.x/1.5.0.md +++ b/docs/changes/1.x/1.5.0.md @@ -7,6 +7,7 @@ ### Bug fixes - Set writeAttribute return type by [@radarhere](https://github.com/radarhere) fixing [#2204](https://github.com/PHPOffice/PHPWord/issues/2204) in [#2776](https://github.com/PHPOffice/PHPWord/pull/2776) +- Writer RTF: Support for various underline styles, doublestrikethrough, smallcaps, allcaps, fgcolor, hidden, scale, spacing, kerning, position, lang, noproof, and bgcolor in Font by [@rasamassen](https://github.com/rasamassen) in [#2819](https://github.com/PHPOffice/PHPWord/pull/2819), also fixing [#321](https://github.com/PHPOffice/PHPWord/issues/321) ### Miscellaneous @@ -16,4 +17,4 @@ ### BC Breaks -### Notes \ No newline at end of file +### Notes diff --git a/src/PhpWord/Style/Language.php b/src/PhpWord/Style/Language.php index 641ed7b41e..e4db89913e 100644 --- a/src/PhpWord/Style/Language.php +++ b/src/PhpWord/Style/Language.php @@ -24,6 +24,7 @@ * Language * A couple of predefined values are defined here, see the websites below for more values. * + * @see https://learn.microsoft.com/en-us/openspecs/office_standards/ms-oe376/6c085406-a698-4e12-9d4d-c3b0ee3dbc4a * @see http://www.datypic.com/sc/ooxml/t-w_CT_Language.html * @see https://technet.microsoft.com/en-us/library/cc287874(v=office.12).aspx */ @@ -126,6 +127,7 @@ public function __construct(?string $latin = null, ?string $eastAsia = null, ?st { if (!empty($latin)) { $this->setLatin($latin); + $this->setLangId($this->convertLocale($this->validateLocale($latin))); } if (!empty($eastAsia)) { $this->setEastAsia($eastAsia); @@ -258,4 +260,29 @@ private function validateLocale($locale) return $locale; } + + /** + * Converts a language from the format xx-xx to decimal. + * + * @param string $latin + * The value for the latin language + * + * @return int + */ + private function convertLocale($latin) + { + if (empty($latin)) { + return 1024; + } + + $locale = strtoupper(str_replace('-', '_', $latin)) . '_ID'; + + if (defined($locale)) { + return constant($locale); + } elseif (defined("self::$locale")) { + return constant("self::$locale"); + } + + return 1024; + } } diff --git a/src/PhpWord/Writer/RTF/Element/AbstractElement.php b/src/PhpWord/Writer/RTF/Element/AbstractElement.php index e007e6aa26..b6d9d91994 100644 --- a/src/PhpWord/Writer/RTF/Element/AbstractElement.php +++ b/src/PhpWord/Writer/RTF/Element/AbstractElement.php @@ -197,13 +197,25 @@ protected function writeFontStyle() if ($this->fontStyle->getColor() != null) { $colorIndex = array_search($this->fontStyle->getColor(), $parentWriter->getColorTable()); if ($colorIndex !== false) { - $styleWriter->setColorIndex($colorIndex + 1); + $styleWriter->setColorIndex((int) $colorIndex + 1); + } + } + if ($this->fontStyle->getFgColor() != null) { + $colorIndex = array_search($this->fontStyle->getFgColor(), $parentWriter->getColorTable()); + if ($colorIndex !== false) { + $styleWriter->setFgColorIndex((int) $colorIndex + 1); + } + } + if ($this->fontStyle->getBgColor() != null) { + $colorIndex = array_search($this->fontStyle->getBgColor(), $parentWriter->getColorTable()); + if ($colorIndex !== false) { + $styleWriter->setBgColorIndex((int) $colorIndex + 1); } } if ($this->fontStyle->getName() != null) { $fontIndex = array_search($this->fontStyle->getName(), $parentWriter->getFontTable()); if ($fontIndex !== false) { - $styleWriter->setNameIndex($fontIndex); + $styleWriter->setNameIndex((int) $fontIndex); } } diff --git a/src/PhpWord/Writer/RTF/Part/Header.php b/src/PhpWord/Writer/RTF/Part/Header.php index 97644fe4ac..23607547e0 100644 --- a/src/PhpWord/Writer/RTF/Part/Header.php +++ b/src/PhpWord/Writer/RTF/Part/Header.php @@ -188,6 +188,7 @@ private function registerFont(): void { $phpWord = $this->getParentWriter()->getPhpWord(); $this->fontTable[] = Settings::getDefaultFontName(); + $this->colorTable[] = Settings::getDefaultFontColor(); // Search named styles $styles = Style::getStyles(); @@ -238,6 +239,7 @@ private function registerFontItems($style): void $this->registerTableItem($this->fontTable, $style->getName(), $defaultFont); $this->registerTableItem($this->colorTable, $style->getColor(), $defaultColor); $this->registerTableItem($this->colorTable, $style->getFgColor(), $defaultColor); + $this->registerTableItem($this->colorTable, $style->getBgColor(), $defaultColor); return; } diff --git a/src/PhpWord/Writer/RTF/Style/Font.php b/src/PhpWord/Writer/RTF/Style/Font.php index f343c0502f..18d118d2a0 100644 --- a/src/PhpWord/Writer/RTF/Style/Font.php +++ b/src/PhpWord/Writer/RTF/Style/Font.php @@ -37,6 +37,16 @@ class Font extends AbstractStyle */ private $colorIndex = 0; + /** + * @var int Font foreground color index + */ + private $fgColorIndex = 0; + + /** + * @var int Font background color index + */ + private $bgColorIndex = 0; + /** * Write style. * @@ -50,20 +60,102 @@ public function write() } $content = ''; - $content .= $this->getValueIf($style->isRTL(), '\rtlch'); - $content .= '\cf' . $this->colorIndex; - $content .= '\f' . $this->nameIndex; - $size = $style->getSize(); - $content .= $this->getValueIf(is_numeric($size), '\fs' . round($size * 2)); + // Underline Keywords + $underlines = [ + FontStyle::UNDERLINE_DASH => '\uldash', + FontStyle::UNDERLINE_DASHHEAVY => '\ulthdash', + FontStyle::UNDERLINE_DASHLONG => '\ulldash', + FontStyle::UNDERLINE_DASHLONGHEAVY => '\ulthldash', + FontStyle::UNDERLINE_DOUBLE => '\uldb', + FontStyle::UNDERLINE_DOTDASH => '\uldashd', + FontStyle::UNDERLINE_DOTDASHHEAVY => '\ulthdashd', + FontStyle::UNDERLINE_DOTDOTDASH => '\uldashdd', + FontStyle::UNDERLINE_DOTDOTDASHHEAVY => '\ulthdashdd', + FontStyle::UNDERLINE_DOTTED => '\uld', + FontStyle::UNDERLINE_DOTTEDHEAVY => '\ulthd', + FontStyle::UNDERLINE_HEAVY => '\ulth', + FontStyle::UNDERLINE_SINGLE => '\ul', + FontStyle::UNDERLINE_WAVY => '\ulwave', + FontStyle::UNDERLINE_WAVYDOUBLE => '\ululdbwave', + FontStyle::UNDERLINE_WAVYHEAVY => '\ulhwave', + FontStyle::UNDERLINE_WORDS => '\ulw', + ]; + + // Style Name + + // Font name/family + $content .= $this->getValueIf($style->getName() !== null, '\f' . $this->nameIndex); + + // Language + if ($style->getLang() !== null) { + if ($style->isNoProof()) { + $content .= $this->getValueIf($style->getLang()->getLangId() !== null, '\langnp' . $style->getLang()->getLangId()); + } else { + $content .= $this->getValueIf($style->getLang()->getLangId() !== null, '\lang' . $style->getLang()->getLangId()); + } + } + // Color + $content .= $this->getValueIf($style->getColor() !== null, '\cf' . $this->colorIndex); + + // Size + $content .= $this->getValueIf($style->getSize() !== null, '\fs' . round($style->getSize() * 2)); + + // Bold, italic $content .= $this->getValueIf($style->isBold(), '\b'); + $content .= $this->getValueIf($style->isBold() === false, '\b0'); $content .= $this->getValueIf($style->isItalic(), '\i'); - $content .= $this->getValueIf($style->getUnderline() != FontStyle::UNDERLINE_NONE, '\ul'); + $content .= $this->getValueIf($style->isItalic() === false, '\i0'); + + // Strikethrough, double strikethrough $content .= $this->getValueIf($style->isStrikethrough(), '\strike'); + $content .= $this->getValueIf($style->isDoubleStrikethrough(), '\striked1'); + $content .= $this->getValueIf($style->isStrikethrough() === false && $style->isDoubleStrikethrough() === false, '\strike0'); + + // Small caps, all caps + $content .= $this->getValueIf($style->isSmallCaps(), '\scaps'); + $content .= $this->getValueIf($style->isAllCaps(), '\caps'); + + // Hidden text + $content .= $this->getValueIf($style->isHidden(), '\v'); + $content .= $this->getValueIf($style->isHidden() === false, '\v0'); + + // Underline + if (isset($underlines[$style->getUnderline()])) { + $content .= $underlines[$style->getUnderline()]; + } + + // Foreground color + $content .= $this->getValueIf($style->getFgColor() !== null, '\highlight' . $this->fgColorIndex); + + // Superscript/subscript $content .= $this->getValueIf($style->isSuperScript(), '\super'); $content .= $this->getValueIf($style->isSubScript(), '\sub'); + // Spacing + $content .= $this->getValueIf($style->getScale() !== null, '\charscalex' . round($style->getScale() ?? 0)); + $content .= $this->getValueIf($style->getSpacing() !== null, '\expnd' . round($style->getSpacing() * 0.2)); + $content .= $this->getValueIf($style->getSpacing() !== null, '\expndtw' . round($style->getSpacing() ?? 0)); + $content .= $this->getValueIf($style->getKerning() !== null, '\kerning' . round($style->getKerning() * 2)); + + // noProof + $content .= $this->getValueIf($style->isNoProof(), '\noproof\lang1024'); + + // Bakground-Color + $content .= $this->getValueIf($style->getBgColor() !== null, '\chshdng0\chcbpat' . $this->bgColorIndex . '\cb' . $this->bgColorIndex); + + // RTL + $content .= $this->getValueIf($style->isRTL(), '\rtlch'); + $content .= $this->getValueIf($style->isRTL() === false, '\ltrch'); + + // Position + $content .= $this->getValueIf($style->getPosition() !== null, '\up' . $style->getPosition()); + + if (empty($content)) { + return $content; + } + return $content . ' '; } @@ -86,4 +178,24 @@ public function setColorIndex($value = 0): void { $this->colorIndex = $value; } + + /** + * Set font foreground color index. + * + * @param int $value + */ + public function setFgColorIndex($value = 0): void + { + $this->fgColorIndex = $value; + } + + /** + * Set font background color index. + * + * @param int $value + */ + public function setBgColorIndex($value = 0): void + { + $this->bgColorIndex = $value; + } } diff --git a/tests/PhpWordTests/Escaper/RtfEscaper2Test.php b/tests/PhpWordTests/Escaper/RtfEscaper2Test.php index d65b543f21..97924dc5e2 100644 --- a/tests/PhpWordTests/Escaper/RtfEscaper2Test.php +++ b/tests/PhpWordTests/Escaper/RtfEscaper2Test.php @@ -23,7 +23,7 @@ */ class RtfEscaper2Test extends \PHPUnit\Framework\TestCase { - const HEADER = '\\pard\\nowidctlpar {\\cf0\\f0 '; + const HEADER = '\\pard\\nowidctlpar {'; const TRAILER = '}\\par'; public function escapestring($str) diff --git a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php index 1aebea52f0..b20bb6bda9 100644 --- a/tests/PhpWordTests/Escaper/RtfEscaper3Test.php +++ b/tests/PhpWordTests/Escaper/RtfEscaper3Test.php @@ -25,8 +25,8 @@ */ class RtfEscaper3Test extends \PHPUnit\Framework\TestCase { - const HEADER = '\\pard\\nowidctlpar \ql{\\cf0\\f0 '; - const HEADER_RTL = '\\pard\\nowidctlpar \qr{\\rtlch\\cf0\\f0 '; + const HEADER = '\\pard\\nowidctlpar \ql{\ltrch '; + const HEADER_RTL = '\\pard\\nowidctlpar \qr{\\rtlch '; const TRAILER = '}\\par'; protected function tearDown(): void diff --git a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php index 7c1ceac68e..348beec5dd 100644 --- a/tests/PhpWordTests/Writer/RTF/Element/TableTest.php +++ b/tests/PhpWordTests/Writer/RTF/Element/TableTest.php @@ -39,7 +39,6 @@ public function removeCr(WriterTable $field): string public function testTable(): void { - Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new Table(); $width = 100; @@ -59,18 +58,18 @@ public function testTable(): void '\\pard', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', + '{1}\\par', '\\cell', '\\intbl', - '{\\cf0\\f0 2}\\par', + '{2}\\par', '\\cell', '\\row', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '\\ql{\\cf0\\f0 3}\\par', + '{3}\\par', '\\cell', '\\intbl', - '{\\cf0\\f0 4}\par', + '{4}\par', '\\cell', '\\row', '\\pard', @@ -84,7 +83,6 @@ public function testTableStyle(): void { $width = 100; - Settings::setDefaultRtl(false); $parentWriter = new RTF(); Style::addTableStyle('TableStyle', ['borderSize' => 6, 'borderColor' => '006699']); @@ -102,7 +100,7 @@ public function testTableStyle(): void '\\clbrdrr\\brdrs\\brdrw2\\brdrcf0', "\\cellx$width ", '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', + '{1}\\par', '\\cell', '\\row', '\\pard', @@ -116,7 +114,6 @@ public function testTableStyleNotExisting(): void { $width = 100; - Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new Table('TableStyleNotExisting'); @@ -128,7 +125,7 @@ public function testTableStyleNotExisting(): void '\\pard', "\\trowd \\cellx$width ", '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', + '{1}\\par', '\\cell', '\\row', '\\pard', @@ -142,7 +139,6 @@ public function testTableCellStyle(): void { $width = 100; - Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new Table(); @@ -158,7 +154,7 @@ public function testTableCellStyle(): void '\\clbrdrr\\brdrdot\\brdrw2\\brdrcf0', "\\cellx$width ", '\\intbl', - '\\ql{\\cf0\\f0 1}\\par', + '{1}\\par', '\\cell', '\\row', '\\pard', diff --git a/tests/PhpWordTests/Writer/RTF/Element2Test.php b/tests/PhpWordTests/Writer/RTF/Element2Test.php index 2220d93b68..a6afbb8497 100644 --- a/tests/PhpWordTests/Writer/RTF/Element2Test.php +++ b/tests/PhpWordTests/Writer/RTF/Element2Test.php @@ -41,25 +41,23 @@ public function removeCr($field): string public function testTextRun(): void { - Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\TextRun(); $element->addText('Hello '); $element->addText('there.'); $textrun = new WriterTextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\ql{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\nowidctlpar {{Hello }{there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } public function testTextRunParagraphStyle(): void { - Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\TextRun(['spaceBefore' => 0, 'spaceAfter' => 0]); $element->addText('Hello '); $element->addText('there.'); $textrun = new WriterTextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\ql\\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\nowidctlpar \\sb0\\sa0{{Hello }{there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -67,12 +65,11 @@ public function testTitle(): void { $parentWriter = new RTF(); $phpWord = new \PhpOffice\PhpWord\PhpWord(); - Settings::setDefaultRtl(false); $phpWord->addTitleStyle(1, [], ['spaceBefore' => 0, 'spaceAfter' => 0]); $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); $elwrite = new WriterTitle($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\ql\\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; + $expect = "\\pard\\nowidctlpar \\sb0\\sa0{\\outlinelevel0{First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); Settings::setDefaultRtl(null); } diff --git a/tests/PhpWordTests/Writer/RTF/ElementTest.php b/tests/PhpWordTests/Writer/RTF/ElementTest.php index 36504a18f8..231e12f08f 100644 --- a/tests/PhpWordTests/Writer/RTF/ElementTest.php +++ b/tests/PhpWordTests/Writer/RTF/ElementTest.php @@ -121,18 +121,18 @@ public function testTable(): void '\\pard', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '{\\cf0\\f0 1}\\par', + '{1}\\par', '\\cell', '\\intbl', - '{\\cf0\\f0 2}\\par', + '{2}\\par', '\\cell', '\\row', "\\trowd \\cellx$width \\cellx$width2 ", '\\intbl', - '{\\cf0\\f0 3}\\par', + '{3}\\par', '\\cell', '\\intbl', - '{\\cf0\\f0 4}\par', + '{4}\par', '\\cell', '\\row', '\\pard', @@ -149,7 +149,7 @@ public function testTextRun(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new RTF\Element\TextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar {{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\nowidctlpar {{Hello }{there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -160,7 +160,7 @@ public function testTextRunParagraphStyle(): void $element->addText('Hello '); $element->addText('there.'); $textrun = new RTF\Element\TextRun($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\sb0\\sa0{{\\cf0\\f0 Hello }{\\cf0\\f0 there.}}\\par\n"; + $expect = "\\pard\\nowidctlpar \\sb0\\sa0{{Hello }{there.}}\\par\n"; self::assertEquals($expect, $this->removeCr($textrun)); } @@ -172,7 +172,7 @@ public function testTitle(): void $section = $phpWord->addSection(); $element = $section->addTitle('First Heading', 1); $elwrite = new RTF\Element\Title($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\sb0\\sa0{\\outlinelevel0{\\cf0\\f0 First Heading}\\par\n}"; + $expect = "\\pard\\nowidctlpar \\sb0\\sa0{\\outlinelevel0{First Heading}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } @@ -213,7 +213,7 @@ public function testRubyTitle(): void $element = $section->addTitle($textRun, 1); $elwrite = new RTF\Element\Title($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\sb0\\sa2{\\outlinelevel0{\\cf0\\f0\\fs48\\b base text (ruby)}\\par\n}"; + $expect = "\\pard\\nowidctlpar \\sb0\\sa2{\\outlinelevel0{\\cf0\\fs48\\b base text (ruby)}\\par\n}"; self::assertEquals($expect, $this->removeCr($elwrite)); } } diff --git a/tests/PhpWordTests/Writer/RTF/Style/FontTest.php b/tests/PhpWordTests/Writer/RTF/Style/FontTest.php new file mode 100644 index 0000000000..fc3bf10b46 --- /dev/null +++ b/tests/PhpWordTests/Writer/RTF/Style/FontTest.php @@ -0,0 +1,257 @@ +write()); + } + + /** + * Test font and color. + * See page 131 of RTF Specification 1.9.1 for Font (Character). + * See page 142 of RTF Specification 1.9.1 for Highlighting. + */ + public function testFontColor(): void + { + $parentWriter = new RTF(); + $style = new FontStyle(); + $writer = new FontWriter($style); + $writer->setParentWriter($parentWriter); + + $style->setName('Times New Roman'); + $style->setFallbackFont('serif'); // currently does nothing in RTF, see pg. 18 of spec for implementation + $style->setSize(24); + $style->setColor($style::FGCOLOR_YELLOW); + $style->setFgColor($style::FGCOLOR_RED); + $style->setBgColor('#123456'); + $expect = '\f0\cf0\fs48\highlight0\chshdng0\chcbpat0\cb0 '; + self::assertEquals($expect, $this->removeCr($writer)); + } + + /** + * Test font and color after registering header tables. + */ + public function testFontColorRegistered(): void + { + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + $parentWriter = new RTF($phpWord); + $style = new FontStyle(); + $element = new TextElement(); + $writer = new TextWriter($parentWriter, $element, true); + + $style->setName('Times New Roman'); + $style->setFallbackFont('serif'); // currently does nothing in RTF, see pg. 18 of spec for implementation + $style->setSize(24); + $style->setColor($style::FGCOLOR_YELLOW); + $style->setFgColor($style::FGCOLOR_RED); + $style->setBgColor('#123456'); + + $phpWord->addFontStyle('style1', $style); + $parentWriter->getWriterPart('Header')->write(); + + $element->setText('Test'); + $element->setFontStyle($style); + + $expect = '{\f1\cf2\fs48\highlight3\chshdng0\chcbpat4\cb4 Test}'; + self::assertEquals($expect, $this->removeCr($writer)); + } + + /** + * Test formatting. + * See page 130-133 of RTF Specification 1.9.1 for Font (Character). + */ + public function testFontFormatting(): void + { + $parentWriter = new RTF(); + $style = new FontStyle(); + $writer = new FontWriter($style); + $writer->setParentWriter($parentWriter); + + $style->setAllCaps(true); + $style->setBold(true); + $style->setdoubleStrikethrough(true); + $style->setHidden(true); + $style->setItalic(true); + $style->setNoProof(true); + $style->setSubScript(true); + $expect = '\b\i\striked1\caps\v\sub\noproof\lang1024 '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setSmallCaps(true); + $style->setStrikethrough(true); + $style->setSuperScript(true); + $style->setNoProof(false); + $expect = '\b\i\strike\scaps\v\super '; + self::assertEquals($expect, $this->removeCr($writer)); + + // Disable styles (in case default is enabled) + $style->setBold(false); + $style->setHidden(false); + $style->setItalic(false); + $style->setSmallCaps(false); // should display \caps0\scaps0; currently doesn't work + $style->setStrikethrough(false); + $style->setSuperScript(false); // should display \nosupersub; currently doesn't work + $expect = '\b0\i0\strike0\v0 '; + self::assertEquals($expect, $this->removeCr($writer)); + } + + /** + * Test underline. + * See page 132-133 of RTF Specification 1.9.1 for Formatting. + */ + public function testFontUnderline(): void + { + $parentWriter = new RTF(); + $style = new FontStyle(); + $writer = new FontWriter($style); + $writer->setParentWriter($parentWriter); + + $style->setUnderline($style::UNDERLINE_DASH); + $expect = '\uldash '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DASHHEAVY); + $expect = '\ulthdash '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DASHLONG); + $expect = '\ulldash '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DASHLONGHEAVY); + $expect = '\ulthldash '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DOUBLE); + $expect = '\uldb '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DOTDASH); + $expect = '\uldashd '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DOTDASHHEAVY); + $expect = '\ulthdashd '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DOTDOTDASH); + $expect = '\uldashdd '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DOTDOTDASHHEAVY); + $expect = '\ulthdashdd '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DOTTED); + $expect = '\uld '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_DOTTEDHEAVY); + $expect = '\ulthd '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_HEAVY); + $expect = '\ulth '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_SINGLE); + $expect = '\ul '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_WAVY); + $expect = '\ulwave '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_WAVYDOUBLE); + $expect = '\ululdbwave '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_WAVYHEAVY); + $expect = '\ulhwave '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_WORDS); + $expect = '\ulw '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setUnderline($style::UNDERLINE_NONE); // should display \ulnone\ul0; currently doesn't work + $expect = ''; + self::assertEquals($expect, $this->removeCr($writer)); + } + + /** + * Test language. + * See page 132 of RTF Specification 1.9.1 for Spacing. + */ + public function testFontLang(): void + { + $parentWriter = new RTF(); + $style = new FontStyle(); + $writer = new FontWriter($style); + $writer->setParentWriter($parentWriter); + + $style->setRTL(true); + $style->setLang(Language::KO_KR); + $expect = '\lang1042\rtlch '; + self::assertEquals($expect, $this->removeCr($writer)); + + $style->setRTL(false); + $style->setLang(Language::EN_US); + $expect = '\lang1033\ltrch '; + self::assertEquals($expect, $this->removeCr($writer)); + } + + /** + * Test font spacing settings. + */ + public function testFontSpacing(): void + { + $parentWriter = new RTF(); + $style = new FontStyle(); + $writer = new FontWriter($style); + $writer->setParentWriter($parentWriter); + + $style->setScale(5); + $style->setSpacing(4); + $style->setKerning(100); + $style->setPosition(10); + $expect = '\charscalex5\expnd1\expndtw4\kerning200\up10 '; + self::assertEquals($expect, $this->removeCr($writer)); + } +} diff --git a/tests/PhpWordTests/Writer/RTF/StyleTest.php b/tests/PhpWordTests/Writer/RTF/StyleTest.php index 8ba2bcb9c9..5291635a31 100644 --- a/tests/PhpWordTests/Writer/RTF/StyleTest.php +++ b/tests/PhpWordTests/Writer/RTF/StyleTest.php @@ -126,7 +126,7 @@ public function testRTL(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד', ['RTL' => true]); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\nowidctlpar {\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; + $expect = "\\pard\\nowidctlpar {\\rtlch \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -136,7 +136,7 @@ public function testRTL2(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('אב גד'); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\qr{\\rtlch\\cf0\\f0 \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; + $expect = "\\pard\\nowidctlpar \\qr{\\rtlch \\uc0{\\u1488}\\uc0{\\u1489} \\uc0{\\u1490}\\uc0{\\u1491}}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } @@ -145,17 +145,16 @@ public function testPageBreakLineHeight(): void $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; + $expect = "\\pard\\nowidctlpar \\sl259\\slmult1\\page{New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); } public function testPageBreakLineHeight2(): void { - Settings::setDefaultRtl(false); $parentWriter = new RTF(); $element = new \PhpOffice\PhpWord\Element\Text('New page', null, ['lineHeight' => 1.08, 'pageBreakBefore' => true]); $text = new RTF\Element\Text($parentWriter, $element); - $expect = "\\pard\\nowidctlpar \\ql\\sl259\\slmult1\\page{\\cf0\\f0 New page}\\par\n"; + $expect = "\\pard\\nowidctlpar \\sl259\\slmult1\\page{New page}\\par\n"; self::assertEquals($expect, $this->removeCr($text)); }