Skip to content

Commit

Permalink
Merge branch 'master' into wordunimplemented2
Browse files Browse the repository at this point in the history
  • Loading branch information
oleibman authored Jan 15, 2025
2 parents 5084642 + 337dc27 commit 4280dab
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 44 deletions.
3 changes: 3 additions & 0 deletions docs/changes/1.x/1.4.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -13,6 +15,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

Expand Down
10 changes: 9 additions & 1 deletion docs/usage/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ $phpWord->setDefaultFontName('Times New Roman');
$phpWord->setDefaultFontSize(12);
```

Or you can specify Asian Font

``` php
<?php

$phpWord->setDefaultAsianFontName('標楷體');
```

## Document settings

Settings for the generated document can be set using ``$phpWord->getSettings()``
Expand Down Expand Up @@ -380,4 +388,4 @@ To control whether or not words in all capital letters shall be hyphenated use t
<?php

$phpWord->getSettings()->setDoNotHyphenateCaps(true);
```
```
18 changes: 18 additions & 0 deletions src/PhpWord/PhpWord.php
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,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.
*
Expand Down
26 changes: 26 additions & 0 deletions src/PhpWord/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,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.
*
Expand Down Expand Up @@ -357,6 +364,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.
*/
Expand All @@ -371,6 +386,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.
*
Expand Down
52 changes: 23 additions & 29 deletions src/PhpWord/Shared/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,21 +203,21 @@ protected static function parseInlineStyle($node, &$styles)
break;
case 'width':
// tables, cells
$val = $val === 'auto' ? '100%' : $val;
if (false !== strpos($val, '%')) {
// e.g. <table width="100%"> or <td width="50%">
$styles['width'] = (int) $val * 50;
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::PERCENT;
} else {
// e.g. <table width="250> where "250" = 250px (always pixels)
$styles['width'] = Converter::pixelToTwip($val);
$styles['width'] = Converter::pixelToTwip(self::convertHtmlSize($val));
$styles['unit'] = \PhpOffice\PhpWord\SimpleType\TblWidth::TWIP;
}

break;
case 'cellspacing':
// tables e.g. <table cellspacing="2">, where "2" = 2px (always pixels)
$val = (int) $val . 'px';
$styles['cellSpacing'] = Converter::cssToTwip($val);
$styles['cellSpacing'] = Converter::pixelToTwip(self::convertHtmlSize($val));

break;
case 'bgcolor':
Expand Down Expand Up @@ -1046,36 +1046,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;
Expand Down Expand Up @@ -1358,4 +1334,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;
}
}
3 changes: 2 additions & 1 deletion src/PhpWord/Writer/Word2007/Part/Styles.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,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();
Expand All @@ -96,7 +97,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');
Expand Down
12 changes: 12 additions & 0 deletions tests/PhpWordTests/PhpWordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
14 changes: 14 additions & 0 deletions tests/PhpWordTests/SettingsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,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.
*/
Expand Down
57 changes: 44 additions & 13 deletions tests/PhpWordTests/Shared/HtmlTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use PhpOffice\PhpWord\SimpleType\LineSpacingRule;
use PhpOffice\PhpWord\Style;
use PhpOffice\PhpWord\Style\Font;
use PhpOffice\PhpWord\SimpleType\TblWidth;
use PhpOffice\PhpWord\Style\Paragraph;
use PhpOffice\PhpWordTests\AbstractWebServerEmbedded;
use PhpOffice\PhpWordTests\TestHelperDOCX;
Expand Down Expand Up @@ -209,11 +210,11 @@ public function testSpanClassName(): void
}

/**
* Test underline.
* Test text-decoration style.
*/
public function testParseUnderline(): void
public function testParseTextDecoration(): void
{
$html = '<u>test</u>';
$html = '<span style="text-decoration: underline;">test</span>';
$phpWord = new PhpWord();
$section = $phpWord->addSection();
Html::addHtml($section, $html);
Expand All @@ -224,11 +225,11 @@ public function testParseUnderline(): void
}

/**
* Test text-decoration style.
* Test underline.
*/
public function testParseTextDecoration(): void
public function testParseUnderline(): void
{
$html = '<span style="text-decoration: underline;">test</span>';
$html = '<u>test</u>';
$phpWord = new PhpWord();
$section = $phpWord->addSection();
Html::addHtml($section, $html);
Expand All @@ -238,6 +239,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 = '<table width="' . $htmlSize . '"><tr><td>A</td></tr></table>';
$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.
*/
Expand Down Expand Up @@ -514,31 +534,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'));

// <td style="width: 25%; ...
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tcPr/w:tcW';
self::assertTrue($doc->elementExists($xpath));
self::assertEquals(25 * 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'));

// <table width="400" .. 400px = 6000 twips (400 / 96 * 1440)
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr/w:tc/w:tcPr/w:tcW';
self::assertTrue($doc->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'));

// <th style="width: 50pt; .. 50pt = 750 twips (50 / 72 * 1440)
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr[2]/w:tc[2]/w:tcPr/w:tcW';
self::assertTrue($doc->elementExists($xpath));
self::assertEquals(1000, $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'));

// <th width="300" .. 300px = 4500 twips (300 / 96 * 1440)
$xpath = '/w:document/w:body/w:tbl/w:tr/w:tc/w:tbl/w:tr[3]/w:tc/w:tcPr/w:tcW';
self::assertTrue($doc->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'));
}

/**
Expand Down Expand Up @@ -652,7 +672,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));
Expand Down Expand Up @@ -685,7 +705,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));
Expand Down Expand Up @@ -1278,4 +1298,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],
];
}
}

0 comments on commit 4280dab

Please sign in to comment.