From f9da10ecd51696fe3e9291c5bbe44d3ba737cff8 Mon Sep 17 00:00:00 2001 From: Progi1984 Date: Tue, 14 Jan 2025 13:19:05 +0100 Subject: [PATCH 1/2] Reader HTML: Support for differents size units for table (#2725) --- docs/changes/1.x/1.4.0.md | 1 + src/PhpWord/Shared/Html.php | 52 +++++++++++------------ tests/PhpWordTests/Shared/HtmlTest.php | 57 ++++++++++++++++++++------ 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index 0a08848037..c191fea948 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -13,6 +13,7 @@ - Writer ODText: Support for images inside a textRun by [@Progi1984](https://github.com/Progi1984) fixing [#2240](https://github.com/PHPOffice/PHPWord/issues/2240) in [#2668](https://github.com/PHPOffice/PHPWord/pull/2668) - Allow vAlign and vMerge on Style\Cell to be set to null by [@SpraxDev](https://github.com/SpraxDev) fixing [#2673](https://github.com/PHPOffice/PHPWord/issues/2673) in [#2676](https://github.com/PHPOffice/PHPWord/pull/2676) +- Reader HTML: Support for differents size units for table by [@Progi1984](https://github.com/Progi1984) fixing [#2384](https://github.com/PHPOffice/PHPWord/issues/2384), [#2701](https://github.com/PHPOffice/PHPWord/issues/2701) in [#2725](https://github.com/PHPOffice/PHPWord/pull/2725) ### Miscellaneous diff --git a/src/PhpWord/Shared/Html.php b/src/PhpWord/Shared/Html.php index 36a66f4110..11a6b39d54 100644 --- a/src/PhpWord/Shared/Html.php +++ b/src/PhpWord/Shared/Html.php @@ -128,21 +128,21 @@ protected static function parseInlineStyle($node, $styles = []) break; case 'width': // tables, cells + $val = $val === 'auto' ? '100%' : $val; if (false !== strpos($val, '%')) { // e.g. or
$styles['width'] = (int) $val * 50; $styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT; } else { // e.g. , where "2" = 2px (always pixels) - $val = (int) $val . 'px'; - $styles['cellSpacing'] = Converter::cssToTwip($val); + $styles['cellSpacing'] = Converter::pixelToTwip(self::convertHtmlSize($val)); break; case 'bgcolor': @@ -902,36 +902,12 @@ protected static function parseImage($node, $element) break; case 'width': - $width = $attribute->value; - - // pt - if (false !== strpos($width, 'pt')) { - $width = Converter::pointToPixel((float) str_replace('pt', '', $width)); - } - - // px - if (false !== strpos($width, 'px')) { - $width = str_replace('px', '', $width); - } - - $style['width'] = $width; + $style['width'] = self::convertHtmlSize($attribute->value); $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; case 'height': - $height = $attribute->value; - - // pt - if (false !== strpos($height, 'pt')) { - $height = Converter::pointToPixel((float) str_replace('pt', '', $height)); - } - - // px - if (false !== strpos($height, 'px')) { - $height = str_replace('px', '', $height); - } - - $style['height'] = $height; + $style['height'] = self::convertHtmlSize($attribute->value); $style['unit'] = \PhpOffice\PhpWord\Style\Image::UNIT_PX; break; @@ -1211,4 +1187,22 @@ private static function convertRgb(string $rgb): string return trim($rgb, '# '); } + + /** + * Transform HTML sizes (pt, px) in pixels. + */ + protected static function convertHtmlSize(string $size): float + { + // pt + if (false !== strpos($size, 'pt')) { + return Converter::pointToPixel((float) str_replace('pt', '', $size)); + } + + // px + if (false !== strpos($size, 'px')) { + return (float) str_replace('px', '', $size); + } + + return (float) $size; + } } diff --git a/tests/PhpWordTests/Shared/HtmlTest.php b/tests/PhpWordTests/Shared/HtmlTest.php index e6a0bd4953..3869f9608d 100644 --- a/tests/PhpWordTests/Shared/HtmlTest.php +++ b/tests/PhpWordTests/Shared/HtmlTest.php @@ -25,6 +25,7 @@ use PhpOffice\PhpWord\Shared\Html; use PhpOffice\PhpWord\SimpleType\Jc; use PhpOffice\PhpWord\SimpleType\LineSpacingRule; +use PhpOffice\PhpWord\SimpleType\TblWidth; use PhpOffice\PhpWord\Style\Paragraph; use PhpOffice\PhpWordTests\AbstractWebServerEmbedded; use PhpOffice\PhpWordTests\TestHelperDOCX; @@ -156,11 +157,11 @@ public function testParseStyleTableClassName(): void } /** - * Test underline. + * Test text-decoration style. */ - public function testParseUnderline(): void + public function testParseTextDecoration(): void { - $html = 'test'; + $html = 'test'; $phpWord = new PhpWord(); $section = $phpWord->addSection(); Html::addHtml($section, $html); @@ -171,11 +172,11 @@ public function testParseUnderline(): void } /** - * Test text-decoration style. + * Test underline. */ - public function testParseTextDecoration(): void + public function testParseUnderline(): void { - $html = 'test'; + $html = 'test'; $phpWord = new PhpWord(); $section = $phpWord->addSection(); Html::addHtml($section, $html); @@ -185,6 +186,25 @@ public function testParseTextDecoration(): void self::assertEquals('single', $doc->getElementAttribute('/w:document/w:body/w:p/w:r/w:rPr/w:u', 'w:val')); } + /** + * Test width. + * + * @dataProvider providerParseWidth + */ + public function testParseWidth(string $htmlSize, float $docxSize, string $docxUnit): void + { + $html = '
A
'; + $phpWord = new PhpWord(); + $section = $phpWord->addSection(); + + Html::addHtml($section, $html); + $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); + $xpath = '/w:document/w:body/w:tbl/w:tblPr/w:tblW'; + self::assertTrue($doc->elementExists($xpath)); + self::assertEquals($docxSize, $doc->getElement($xpath)->getAttribute('w:w')); + self::assertEquals($docxUnit, $doc->getElement($xpath)->getAttribute('w:type')); + } + /** * Test font-variant style. */ @@ -461,31 +481,31 @@ public function testParseTableAndCellWidth(): void $xpath = '/w:document/w:body/w:tbl/w:tblGrid/w:gridCol'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(25 * 50, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); //
elementExists($xpath)); self::assertEquals(6000, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); // elementExists($xpath)); self::assertEquals(4500, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); } /** @@ -599,7 +619,7 @@ public function testParseTableCellspacingRowBgColor(): void $xpath = '/w:document/w:body/w:tbl/w:tblPr/w:tblCellSpacing'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(3 * 15, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('dxa', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::TWIP, $doc->getElement($xpath)->getAttribute('w:type')); $xpath = '/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:tcPr/w:shd'; self::assertTrue($doc->elementExists($xpath)); @@ -632,7 +652,7 @@ public function testParseTableStyleAttributeInlineStyle(): void $xpath = '/w:document/w:body/w:tbl/w:tblPr/w:tblW'; self::assertTrue($doc->elementExists($xpath)); self::assertEquals(100 * 50, $doc->getElement($xpath)->getAttribute('w:w')); - self::assertEquals('pct', $doc->getElement($xpath)->getAttribute('w:type')); + self::assertEquals(TblWidth::PERCENT, $doc->getElement($xpath)->getAttribute('w:type')); $xpath = '/w:document/w:body/w:tbl/w:tr[1]/w:tc[1]/w:tcPr/w:shd'; self::assertTrue($doc->elementExists($xpath)); @@ -1225,4 +1245,15 @@ public function testDontDecodeAlreadyEncodedDoubleQuotes(): void $doc = TestHelperDOCX::getDocument($phpWord, 'Word2007'); self::assertIsObject($doc); } + + public static function providerParseWidth(): array + { + return [ + ['auto', 5000, TblWidth::PERCENT], + ['100%', 5000, TblWidth::PERCENT], + ['200pt', 3999.999999999999, TblWidth::TWIP], + ['300px', 4500, TblWidth::TWIP], + ['400', 6000, TblWidth::TWIP], + ]; + } } From 337dc27f4b08ffce1aae0f749ebeae942dd4806a Mon Sep 17 00:00:00 2001 From: Jui-Nan Lin Date: Wed, 15 Jan 2025 14:25:15 +0800 Subject: [PATCH 2/2] feat(font): add default asian font name (#2714) * feat(font): add default asian font name * doc: examples and changes * test: add test for DefaultAsianFontName * fix: specify the return value type Co-authored-by: Progi1984 * test: test set/get function in PHPWord * style: removed unused annotiation --------- Co-authored-by: Jui-Nan Lin Co-authored-by: Progi1984 --- docs/changes/1.x/1.4.0.md | 2 ++ docs/usage/introduction.md | 10 +++++++- src/PhpWord/PhpWord.php | 18 ++++++++++++++ src/PhpWord/Settings.php | 26 +++++++++++++++++++++ src/PhpWord/Writer/Word2007/Part/Styles.php | 3 ++- tests/PhpWordTests/PhpWordTest.php | 12 ++++++++++ tests/PhpWordTests/SettingsTest.php | 14 +++++++++++ 7 files changed, 83 insertions(+), 2 deletions(-) diff --git a/docs/changes/1.x/1.4.0.md b/docs/changes/1.x/1.4.0.md index c191fea948..1c1557a940 100644 --- a/docs/changes/1.x/1.4.0.md +++ b/docs/changes/1.x/1.4.0.md @@ -4,6 +4,8 @@ ## Enhancements +- Default Font: Allow specify Asisn font and Latin font separately + - Writer ODText: Support for ListItemRun by [@Progi1984](https://github.com/Progi1984) fixing [#2159](https://github.com/PHPOffice/PHPWord/issues/2159), [#2620](https://github.com/PHPOffice/PHPWord/issues/2620) in [#2669](https://github.com/PHPOffice/PHPWord/pull/2669) - Writer HTML: Support for vAlign in Tables by [@SpraxDev](https://github.com/SpraxDev) in [#2675](https://github.com/PHPOffice/PHPWord/pull/2675) - Added support for PHP 8.4 by [@Progi1984](https://github.com/Progi1984) in [#2660](https://github.com/PHPOffice/PHPWord/pull/2660) diff --git a/docs/usage/introduction.md b/docs/usage/introduction.md index 7a3d153d95..6aa42aaae0 100644 --- a/docs/usage/introduction.md +++ b/docs/usage/introduction.md @@ -137,6 +137,14 @@ $phpWord->setDefaultFontName('Times New Roman'); $phpWord->setDefaultFontSize(12); ``` +Or you can specify Asian Font + +``` php +setDefaultAsianFontName('標楷體'); +``` + ## Document settings Settings for the generated document can be set using ``$phpWord->getSettings()`` @@ -380,4 +388,4 @@ To control whether or not words in all capital letters shall be hyphenated use t getSettings()->setDoNotHyphenateCaps(true); -``` \ No newline at end of file +``` diff --git a/src/PhpWord/PhpWord.php b/src/PhpWord/PhpWord.php index f96bdcf401..aa62a76f0d 100644 --- a/src/PhpWord/PhpWord.php +++ b/src/PhpWord/PhpWord.php @@ -257,6 +257,24 @@ public function setDefaultFontName($fontName): void Settings::setDefaultFontName($fontName); } + /** + * Get default asian font name. + */ + public function getDefaultAsianFontName(): string + { + return Settings::getDefaultAsianFontName(); + } + + /** + * Set default font name. + * + * @param string $fontName + */ + public function setDefaultAsianFontName($fontName): void + { + Settings::setDefaultAsianFontName($fontName); + } + /** * Get default font size. * diff --git a/src/PhpWord/Settings.php b/src/PhpWord/Settings.php index a2c461e29a..0cbfed7988 100644 --- a/src/PhpWord/Settings.php +++ b/src/PhpWord/Settings.php @@ -118,6 +118,13 @@ class Settings */ private static $defaultFontName = self::DEFAULT_FONT_NAME; + /** + * Default font name. + * + * @var string + */ + private static $defaultAsianFontName = self::DEFAULT_FONT_NAME; + /** * Default font size. * @@ -355,6 +362,14 @@ public static function getDefaultFontName(): string return self::$defaultFontName; } + /** + * Get default font name. + */ + public static function getDefaultAsianFontName(): string + { + return self::$defaultAsianFontName; + } + /** * Set default font name. */ @@ -369,6 +384,17 @@ public static function setDefaultFontName(string $value): bool return false; } + public static function setDefaultAsianFontName(string $value): bool + { + if (trim($value) !== '') { + self::$defaultAsianFontName = $value; + + return true; + } + + return false; + } + /** * Get default font size. * diff --git a/src/PhpWord/Writer/Word2007/Part/Styles.php b/src/PhpWord/Writer/Word2007/Part/Styles.php index bda1e653b7..c57c1e58be 100644 --- a/src/PhpWord/Writer/Word2007/Part/Styles.php +++ b/src/PhpWord/Writer/Word2007/Part/Styles.php @@ -84,6 +84,7 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void { $phpWord = $this->getParentWriter()->getPhpWord(); $fontName = $phpWord->getDefaultFontName(); + $asianFontName = $phpWord->getDefaultAsianFontName(); $fontSize = $phpWord->getDefaultFontSize(); $language = $phpWord->getSettings()->getThemeFontLang(); $latinLanguage = ($language == null || $language->getLatin() === null) ? 'en-US' : $language->getLatin(); @@ -95,7 +96,7 @@ private function writeDefaultStyles(XMLWriter $xmlWriter, $styles): void $xmlWriter->startElement('w:rFonts'); $xmlWriter->writeAttribute('w:ascii', $fontName); $xmlWriter->writeAttribute('w:hAnsi', $fontName); - $xmlWriter->writeAttribute('w:eastAsia', $fontName); + $xmlWriter->writeAttribute('w:eastAsia', $asianFontName); $xmlWriter->writeAttribute('w:cs', $fontName); $xmlWriter->endElement(); // w:rFonts $xmlWriter->startElement('w:sz'); diff --git a/tests/PhpWordTests/PhpWordTest.php b/tests/PhpWordTests/PhpWordTest.php index 9ad7b02574..d194f4895d 100644 --- a/tests/PhpWordTests/PhpWordTest.php +++ b/tests/PhpWordTests/PhpWordTest.php @@ -83,6 +83,18 @@ public function testSetGetDefaultFontSize(): void self::assertEquals($fontSize, $phpWord->getDefaultFontSize()); } + /** + * Test set/get default asian font name. + */ + public function testSetGetDefaultAsianFontName(): void + { + $phpWord = new PhpWord(); + $fontName = 'Times New Roman'; + self::assertEquals(Settings::DEFAULT_FONT_NAME, $phpWord->getDefaultAsianFontName()); + $phpWord->setDefaultAsianFontName($fontName); + self::assertEquals($fontName, $phpWord->getDefaultAsianFontName()); + } + /** * Test set default paragraph style. */ diff --git a/tests/PhpWordTests/SettingsTest.php b/tests/PhpWordTests/SettingsTest.php index 67099650aa..cf8e12b205 100644 --- a/tests/PhpWordTests/SettingsTest.php +++ b/tests/PhpWordTests/SettingsTest.php @@ -217,6 +217,20 @@ public function testSetGetDefaultFontName(): void self::assertEquals('Times New Roman', Settings::getDefaultFontName()); } + /** + * Test set/get default font name. + */ + public function testSetGetDefaultAsianFontName(): void + { + self::assertEquals(Settings::DEFAULT_FONT_NAME, Settings::getDefaultAsianFontName()); + self::assertFalse(Settings::setDefaultAsianFontName(' ')); + self::assertEquals(Settings::DEFAULT_FONT_NAME, Settings::getDefaultAsianFontName()); + self::assertTrue(Settings::setDefaultAsianFontName('Times New Roman')); + self::assertEquals('Times New Roman', Settings::getDefaultAsianFontName()); + self::assertFalse(Settings::setDefaultAsianFontName(' ')); + self::assertEquals('Times New Roman', Settings::getDefaultAsianFontName()); + } + /** * Test set/get default font size. */