Refactor new image styles and create `Word2007/Style/Image` class

This commit is contained in:
Ivan Lanin 2014-05-04 21:16:12 +07:00
parent 6898ada0e0
commit 42c712e334
5 changed files with 316 additions and 271 deletions

View File

@ -8,19 +8,16 @@ PHPWord license is changed from LGPL 2.1 to LGPL 3 in this release.
### Features
-
- Image: Ability to define relative and absolute positioning - @basjan GH-217
### Bugfixes
-
### Deprecated
-
- ...
### Miscellaneous
- License: Change the project license from LGPL 2.1 into LGPL 3.0 - GH-211
- Word2007 Writer: New `Style\Image` class - @ivanlanin
## 0.10.0 - 4 May 2014

View File

@ -26,7 +26,7 @@ $wrappingStyles = array('inline', 'behind', 'infront', 'square', 'tight');
foreach ($wrappingStyles as $wrappingStyle) {
$section->addTextBreak(5);
$section->addText('Wrapping style ' . $wrappingStyle);
$section->addImage('resources/_earth.jpg', array('marginTop' => -1, 'marginLeft' => 1,
$section->addImage('resources/_earth.jpg', array('positioning' => 'relative', 'marginTop' => -1, 'marginLeft' => 1,
'width' => 80, 'height' => 80, 'wrappingStyle' => $wrappingStyle));
$section->addText($text);
}

View File

@ -14,66 +14,61 @@ namespace PhpOffice\PhpWord\Style;
*/
class Image extends AbstractStyle
{
/**
* Wrapping styles
*
* @const string
*/
const WRAPPING_STYLE_INLINE = 'inline';
const WRAPPING_STYLE_SQUARE = 'square';
const WRAPPING_STYLE_TIGHT = 'tight';
const WRAPPING_STYLE_BEHIND = 'behind';
const WRAPPING_STYLE_INFRONT = 'infront';
/**
* Horizontal alignment
*
* @const string
*/
const POSITION_HORIZONTAL_LEFT = 'left';
const POSITION_HORIZONTAL_CENTER = 'centered';
const POSITION_HORIZONTAL_RIGHT = 'right';
/**
* Vertical alignment
*
* @const string
*/
const POSITION_VERTICAL_TOP = 'top';
const POSITION_VERTICAL_CENTER = 'center';
const POSITION_VERTICAL_BOTTOM = 'bottom';
const POSITION_VERTICAL_INSIDE = 'inside';
const POSITION_VERTICAL_OUTSIDE = 'outside';
const POSITION_HORIZONTAL_RELATIVE_MARGIN = 'margin';
const POSITION_HORIZONTAL_RELATIVE_PAGE = 'page';
const POSITION_HORIZONTAL_RELATIVE_COLUMN = 'column';
const POSITION_HORIZONTAL_RELATIVE_CHAR = 'char';
const POSITION_HORIZONTAL_RELATIVE_LMARGIN = 'left-margin-area';
const POSITION_HORIZONTAL_RELATIVE_RMARGIN = 'right-margin-area';
const POSITION_HORIZONTAL_RELATIVE_IMARGIN = 'inner-margin-area';
const POSITION_HORIZONTAL_RELATIVE_OMARGIN = 'outer-margin-area';
const POSITION_VERTICAL_RELATIVE_MARGIN = 'margin';
const POSITION_VERTICAL_RELATIVE_PAGE = 'page';
const POSITION_VERTICAL_RELATIVE_LINE = 'line';
const POSITION_VERTICAL_RELATIVE_TMARGIN = 'top-margin-area';
const POSITION_VERTICAL_RELATIVE_BMARGIN = 'bottom-margin-area';
const POSITION_VERTICAL_RELATIVE_IMARGIN = 'inner-margin-area';
const POSITION_VERTICAL_RELATIVE_OMARGIN = 'outer-margin-area';
const POSITION_RELATIVE = 'relative';
/**
* Position relative to
*
* @const string
*/
const POSITION_RELATIVE_TO_MARGIN = 'margin';
const POSITION_RELATIVE_TO_PAGE = 'page';
const POSITION_RELATIVE_TO_COLUMN = 'column'; // horizontal only
const POSITION_RELATIVE_TO_CHAR = 'char'; // horizontal only
const POSITION_RELATIVE_TO_LINE = 'line'; // vertical only
const POSITION_RELATIVE_TO_LMARGIN = 'left-margin-area'; // horizontal only
const POSITION_RELATIVE_TO_RMARGIN = 'right-margin-area'; // horizontal only
const POSITION_RELATIVE_TO_TMARGIN = 'top-margin-area'; // vertical only
const POSITION_RELATIVE_TO_BMARGIN = 'bottom-margin-area'; // vertical only
const POSITION_RELATIVE_TO_IMARGIN = 'inner-margin-area';
const POSITION_RELATIVE_TO_OMARGIN = 'outer-margin-area';
/**
* Position type, relative/absolute
*
* @const string
*/
const POSITION_ABSOLUTE = 'absolute';
const POSITION_RELATIVE = 'relative';
/**
* Image width
@ -117,6 +112,13 @@ class Image extends AbstractStyle
*/
private $wrappingStyle;
/**
* Positioning type (relative or absolute)
*
* @var string
*/
private $positioning;
/**
* Horizontal alignment
*
@ -145,29 +147,16 @@ class Image extends AbstractStyle
*/
private $posVerticalRel;
/**
* Positioning type (Relative or Absolute)
*
* @var string
*/
private $positioning;
/**
* Create new image style
*/
public function __construct()
{
$this->width = null;
$this->height = null;
$this->align = null;
$this->marginTop = null;
$this->marginLeft = null;
$this->setWrappingStyle(self::WRAPPING_STYLE_INLINE);
$this->setPositioning(self::POSITION_RELATIVE);
$this->setPosHorizontal(self::POSITION_HORIZONTAL_LEFT);
$this->setPosHorizontalRel(self::POSITION_HORIZONTAL_RELATIVE_CHAR);
$this->setPosHorizontalRel(self::POSITION_RELATIVE_TO_CHAR);
$this->setPosVertical(self::POSITION_VERTICAL_TOP);
$this->setPosVerticalRel(self::POSITION_VERTICAL_RELATIVE_LINE);
$this->setPosVerticalRel(self::POSITION_RELATIVE_TO_LINE);
}
/**
@ -181,11 +170,11 @@ class Image extends AbstractStyle
/**
* Set width
*
* @param int $pValue
* @param int $value
*/
public function setWidth($pValue = null)
public function setWidth($value = null)
{
$this->width = $pValue;
$this->width = $value;
}
/**
@ -199,11 +188,11 @@ class Image extends AbstractStyle
/**
* Set height
*
* @param int $pValue
* @param int $value
*/
public function setHeight($pValue = null)
public function setHeight($value = null)
{
$this->height = $pValue;
$this->height = $value;
}
/**
@ -217,11 +206,11 @@ class Image extends AbstractStyle
/**
* Set alignment
*
* @param string $pValue
* @param string $value
*/
public function setAlign($pValue = null)
public function setAlign($value = null)
{
$this->align = $pValue;
$this->align = $value;
}
/**
@ -237,12 +226,12 @@ class Image extends AbstractStyle
/**
* Set Margin Top
*
* @param int $pValue
* @return $this
* @param int $value
* @return self
*/
public function setMarginTop($pValue = null)
public function setMarginTop($value = null)
{
$this->marginTop = $pValue;
$this->marginTop = $value;
return $this;
}
@ -259,35 +248,12 @@ class Image extends AbstractStyle
/**
* Set Margin Left
*
* @param int $pValue
* @return $this
* @param int $value
* @return self
*/
public function setMarginLeft($pValue = null)
public function setMarginLeft($value = null)
{
$this->marginLeft = $pValue;
return $this;
}
/**
* Set wrapping style
*
* @param string $wrappingStyle
* @throws \InvalidArgumentException
* @return $this
*/
public function setWrappingStyle($wrappingStyle)
{
switch ($wrappingStyle) {
case self::WRAPPING_STYLE_BEHIND:
case self::WRAPPING_STYLE_INFRONT:
case self::WRAPPING_STYLE_INLINE:
case self::WRAPPING_STYLE_SQUARE:
case self::WRAPPING_STYLE_TIGHT:
$this->wrappingStyle = $wrappingStyle;
break;
default:
throw new \InvalidArgumentException('Wrapping style does not exists');
}
$this->marginLeft = $value;
return $this;
}
@ -302,23 +268,23 @@ class Image extends AbstractStyle
}
/**
* Set positioning type
* Set wrapping style
*
* @param string $positioning
* @param string $wrappingStyle
* @throws \InvalidArgumentException
* @return $this
* @return self
*/
public function setPositioning($positioning)
public function setWrappingStyle($wrappingStyle)
{
switch ($positioning) {
case self::POSITION_RELATIVE:
case self::POSITION_ABSOLUTE:
$this->positioning = $positioning;
break;
default:
throw new InvalidArgumentException('Positioning does not exists');
break;
$enum = array(self::WRAPPING_STYLE_INLINE, self::WRAPPING_STYLE_INFRONT, self::WRAPPING_STYLE_BEHIND,
self::WRAPPING_STYLE_SQUARE, self::WRAPPING_STYLE_TIGHT);
if (in_array($wrappingStyle, $enum)) {
$this->wrappingStyle = $wrappingStyle;
} else {
throw new \InvalidArgumentException('Invalid wrapping style.');
}
return $this;
}
@ -333,24 +299,22 @@ class Image extends AbstractStyle
}
/**
* Set horizontal alignment
* Set positioning type
*
* @param string $alignment
* @param string $positioning
* @throws \InvalidArgumentException
* @return $this
* @return self
*/
public function setPosHorizontal($alignment)
public function setPositioning($positioning)
{
switch ($alignment) {
case self::POSITION_HORIZONTAL_LEFT:
case self::POSITION_HORIZONTAL_CENTER:
case self::POSITION_HORIZONTAL_RIGHT:
$this->posHorizontal = $alignment;
break;
default:
throw new InvalidArgumentException('Horizontal alignment does not exists');
break;
$enum = array(self::POSITION_RELATIVE, self::POSITION_ABSOLUTE);
if (in_array($positioning, $enum)) {
$this->positioning = $positioning;
} else {
throw new \InvalidArgumentException('Invalid positioning.');
}
return $this;
}
@ -365,26 +329,23 @@ class Image extends AbstractStyle
}
/**
* Set vertical alignment
* Set horizontal alignment
*
* @param string $alignment
* @throws \InvalidArgumentException
* @return $this
* @return self
*/
public function setPosVertical($alignment)
public function setPosHorizontal($alignment)
{
switch ($alignment) {
case self::POSITION_VERTICAL_TOP:
case self::POSITION_VERTICAL_CENTER:
case self::POSITION_VERTICAL_BOTTOM:
case self::POSITION_VERTICAL_INSIDE:
case self::POSITION_VERTICAL_OUTSIDE:
$this->posVertical = $alignment;
break;
default:
throw new InvalidArgumentException('Vertical alignment does not exists');
break;
$enum = array(self::POSITION_HORIZONTAL_LEFT, self::POSITION_HORIZONTAL_CENTER,
self::POSITION_HORIZONTAL_RIGHT);
if (in_array($alignment, $enum)) {
$this->posHorizontal = $alignment;
} else {
throw new \InvalidArgumentException('Invalid horizontal alignment.');
}
return $this;
}
@ -399,29 +360,23 @@ class Image extends AbstractStyle
}
/**
* Set horizontal relation
* Set vertical alignment
*
* @param string $relto
* @param string $alignment
* @throws \InvalidArgumentException
* @return $this
* @return self
*/
public function setPosHorizontalRel($relto)
public function setPosVertical($alignment)
{
switch ($relto) {
case self::POSITION_HORIZONTAL_RELATIVE_MARGIN:
case self::POSITION_HORIZONTAL_RELATIVE_PAGE:
case self::POSITION_HORIZONTAL_RELATIVE_COLUMN:
case self::POSITION_HORIZONTAL_RELATIVE_CHAR:
case self::POSITION_HORIZONTAL_RELATIVE_LMARGIN:
case self::POSITION_HORIZONTAL_RELATIVE_RMARGIN:
case self::POSITION_HORIZONTAL_RELATIVE_IMARGIN:
case self::POSITION_HORIZONTAL_RELATIVE_OMARGIN:
$this->posHorizontalRel = $relto;
break;
default:
throw new InvalidArgumentException('Horizontal relation does not exists');
break;
$enum = array(self::POSITION_VERTICAL_TOP, self::POSITION_VERTICAL_CENTER,
self::POSITION_VERTICAL_BOTTOM, self::POSITION_VERTICAL_INSIDE, self::POSITION_VERTICAL_OUTSIDE);
if (in_array($alignment, $enum)) {
$this->posVertical = $alignment;
} else {
throw new \InvalidArgumentException('Invalid vertical alignment.');
}
return $this;
}
@ -436,28 +391,25 @@ class Image extends AbstractStyle
}
/**
* Set vertical relation
* Set horizontal relation
*
* @param string $relto
* @throws \InvalidArgumentException
* @return $this
* @return self
*/
public function setPosVerticalRel($relto)
public function setPosHorizontalRel($relto)
{
switch ($relto) {
case self::POSITION_VERTICAL_RELATIVE_MARGIN:
case self::POSITION_VERTICAL_RELATIVE_PAGE:
case self::POSITION_VERTICAL_RELATIVE_LINE:
case self::POSITION_VERTICAL_RELATIVE_TMARGIN:
case self::POSITION_VERTICAL_RELATIVE_BMARGIN:
case self::POSITION_VERTICAL_RELATIVE_IMARGIN:
case self::POSITION_VERTICAL_RELATIVE_OMARGIN:
$this->posVerticalRel = $relto;
break;
default:
throw new InvalidArgumentException('Vertical relation does not exists');
break;
$enum = array(self::POSITION_RELATIVE_TO_MARGIN, self::POSITION_RELATIVE_TO_PAGE,
self::POSITION_RELATIVE_TO_COLUMN, self::POSITION_RELATIVE_TO_CHAR,
self::POSITION_RELATIVE_TO_LMARGIN, self::POSITION_RELATIVE_TO_RMARGIN,
self::POSITION_RELATIVE_TO_IMARGIN, self::POSITION_RELATIVE_TO_OMARGIN);
if (in_array($relto, $enum)) {
$this->posHorizontalRel = $relto;
} else {
throw new \InvalidArgumentException('Invalid relative horizontal alignment.');
}
return $this;
}
@ -470,4 +422,27 @@ class Image extends AbstractStyle
{
return $this->posVerticalRel;
}
/**
* Set vertical relation
*
* @param string $relto
* @throws \InvalidArgumentException
* @return self
*/
public function setPosVerticalRel($relto)
{
$enum = array(self::POSITION_RELATIVE_TO_MARGIN, self::POSITION_RELATIVE_TO_PAGE,
self::POSITION_RELATIVE_TO_LINE,
self::POSITION_RELATIVE_TO_TMARGIN, self::POSITION_RELATIVE_TO_BMARGIN,
self::POSITION_RELATIVE_TO_IMARGIN, self::POSITION_RELATIVE_TO_OMARGIN);
if (in_array($relto, $enum)) {
$this->posVerticalRel = $relto;
} else {
throw new \InvalidArgumentException('Invalid relative vertical alignment.');
}
return $this;
}
}

View File

@ -10,6 +10,7 @@
namespace PhpOffice\PhpWord\Writer\Word2007\Element;
use PhpOffice\PhpWord\Style\Image as ImageStyle;
use PhpOffice\PhpWord\Writer\Word2007\Style\Image as ImageStyleWriter;
/**
* Image element writer
@ -36,86 +37,30 @@ class Image extends Element
private function writeImage()
{
$rId = $this->element->getRelationId() + ($this->element->isInSection() ? 6 : 0);
$style = $this->element->getStyle();
$width = $style->getWidth();
$height = $style->getHeight();
$align = $style->getAlign();
$marginTop = $style->getMarginTop();
$marginLeft = $style->getMarginLeft();
$wrappingStyle = $style->getWrappingStyle();
$positioning = $style->getPositioning();
$w10wrapType = null;
$imgStyle = '';
if (null !== $width) {
$imgStyle .= 'width:' . $width . 'px;';
}
if (null !== $height) {
$imgStyle .= 'height:' . $height . 'px;';
}
if (null !== $marginTop) {
$imgStyle .= 'margin-top:' . $marginTop . 'px;';
}
if (null !== $marginLeft) {
$imgStyle .= 'margin-left:' . $marginLeft . 'px;';
}
$imgStyle.='position:absolute;mso-width-percent:0;mso-height-percent:0;';
$imgStyle.='mso-width-relative:margin;mso-height-relative:margin;';
switch ($positioning) {
case ImageStyle::POSITION_RELATIVE:
$imgStyle.='mso-position-horizontal:'.$style->getPosHorizontal().';';
$imgStyle.='mso-position-horizontal-relative:'.$style->getPosHorizontalRel().';';
$imgStyle.='mso-position-vertical:'.$style->getPosVertical().';';
$imgStyle.='mso-position-vertical-relative:'.$style->getPosVerticalRel().';';
$imgStyle.='margin-left:0;margin-top:0;';
break;
case ImageStyle::POSITION_ABSOLUTE:
$imgStyle.='mso-position-horizontal-relative:page;';
$imgStyle.='mso-position-vertical-relative:page;';
break;
}
switch ($wrappingStyle) {
case ImageStyle::WRAPPING_STYLE_BEHIND:
$imgStyle .= 'z-index:-251658752;';
break;
case ImageStyle::WRAPPING_STYLE_INFRONT:
$imgStyle .= 'z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;';
break;
case ImageStyle::WRAPPING_STYLE_SQUARE:
$imgStyle .= 'z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;';
$w10wrapType = 'square';
break;
case ImageStyle::WRAPPING_STYLE_TIGHT:
$imgStyle .= 'z-index:251659264;mso-position-horizontal:absolute;mso-position-vertical:absolute;';
$w10wrapType = 'tight';
break;
}
$styleWriter = new ImageStyleWriter($this->xmlWriter, $style);
if (!$this->withoutP) {
$this->xmlWriter->startElement('w:p');
if (!is_null($align)) {
if (!is_null($style->getAlign())) {
$this->xmlWriter->startElement('w:pPr');
$this->xmlWriter->startElement('w:jc');
$this->xmlWriter->writeAttribute('w:val', $align);
$this->xmlWriter->writeAttribute('w:val', $style->getAlign());
$this->xmlWriter->endElement(); // w:jc
$this->xmlWriter->endElement(); // w:pPr
}
}
$this->xmlWriter->startElement('w:r');
$this->xmlWriter->startElement('w:pict');
$this->xmlWriter->startElement('v:shape');
$this->xmlWriter->writeAttribute('type', '#_x0000_t75');
$this->xmlWriter->writeAttribute('style', $imgStyle);
$styleWriter->write();
$this->xmlWriter->startElement('v:imagedata');
$this->xmlWriter->writeAttribute('r:id', 'rId' . $rId);
$this->xmlWriter->writeAttribute('o:title', '');
$this->xmlWriter->endElement(); // v:imagedata
if (!is_null($w10wrapType)) {
$this->xmlWriter->startElement('w10:wrap');
$this->xmlWriter->writeAttribute('type', $w10wrapType);
$this->xmlWriter->endElement(); // w10:wrap
}
$styleWriter->writeW10Wrap();
$this->xmlWriter->endElement(); // v:shape
$this->xmlWriter->endElement(); // w:pict
$this->xmlWriter->endElement(); // w:r
@ -130,28 +75,16 @@ class Image extends Element
private function writeWatermark()
{
$rId = $this->element->getRelationId();
$style = $this->element->getStyle();
$width = $style->getWidth();
$height = $style->getHeight();
$marginLeft = $style->getMarginLeft();
$marginTop = $style->getMarginTop();
$strStyle = 'position:absolute;';
$strStyle .= ' width:' . $width . 'px;';
$strStyle .= ' height:' . $height . 'px;';
if (!is_null($marginTop)) {
$strStyle .= ' margin-top:' . $marginTop . 'px;';
}
if (!is_null($marginLeft)) {
$strStyle .= ' margin-left:' . $marginLeft . 'px;';
}
$style->setPositioning('absolute');
$styleWriter = new ImageStyleWriter($this->xmlWriter, $style);
$this->xmlWriter->startElement('w:p');
$this->xmlWriter->startElement('w:r');
$this->xmlWriter->startElement('w:pict');
$this->xmlWriter->startElement('v:shape');
$this->xmlWriter->writeAttribute('type', '#_x0000_t75');
$this->xmlWriter->writeAttribute('style', $strStyle);
$styleWriter->write();
$this->xmlWriter->startElement('v:imagedata');
$this->xmlWriter->writeAttribute('r:id', 'rId' . $rId);
$this->xmlWriter->writeAttribute('o:title', '');

View File

@ -0,0 +1,140 @@
<?php
/**
* PHPWord
*
* @link https://github.com/PHPOffice/PHPWord
* @copyright 2014 PHPWord
* @license http://www.gnu.org/licenses/lgpl.txt LGPL
*/
namespace PhpOffice\PhpWord\Writer\Word2007\Style;
use PhpOffice\PhpWord\Style\Image as ImageStyle;
/**
* Image style writer
*
* @since 0.10.0
*/
class Image extends AbstractStyle
{
/**
* w10 namespace wrapping type
*
* @var string
*/
private $w10wrap;
/**
* Write style
*/
public function write()
{
if (!($this->style instanceof \PhpOffice\PhpWord\Style\Image)) {
return;
}
$wrapping = $this->style->getWrappingStyle();
$positioning = $this->style->getPositioning();
// Default style array
$styleArray = array(
'mso-width-percent' => '0',
'mso-height-percent' => '0',
'mso-width-relative' => 'margin',
'mso-height-relative' => 'margin',
);
$styleArray = array_merge($styleArray, $this->getElementStyle());
// Absolute/relative positioning
$styleArray['position'] = $positioning;
if ($positioning == ImageStyle::POSITION_ABSOLUTE) {
$styleArray['mso-position-horizontal-relative'] = 'page';
$styleArray['mso-position-vertical-relative'] = 'page';
} elseif ($positioning == ImageStyle::POSITION_RELATIVE) {
$styleArray['mso-position-horizontal'] = $this->style->getPosHorizontal();
$styleArray['mso-position-vertical'] = $this->style->getPosVertical();
$styleArray['mso-position-horizontal-relative'] = $this->style->getPosHorizontalRel();
$styleArray['mso-position-vertical-relative'] = $this->style->getPosVerticalRel();
$styleArray['margin-left'] = 0;
$styleArray['margin-top'] = 0;
}
// Wrapping style
if ($wrapping == ImageStyle::WRAPPING_STYLE_INLINE) {
// Nothing to do when inline
} elseif ($wrapping == ImageStyle::WRAPPING_STYLE_BEHIND) {
$styleArray['z-index'] = -251658752;
} else {
$styleArray['z-index'] = 251659264;
$styleArray['mso-position-horizontal'] = 'absolute';
$styleArray['mso-position-vertical'] = 'absolute';
}
// w10 wrapping
if ($wrapping == ImageStyle::WRAPPING_STYLE_SQUARE) {
$this->w10wrap = 'square';
} elseif ($wrapping == ImageStyle::WRAPPING_STYLE_TIGHT) {
$this->w10wrap = 'tight';
}
$imageStyle = $this->assembleStyle($styleArray);
$this->xmlWriter->writeAttribute('style', $imageStyle);
}
/**
* Write w10 wrapping
*
* @return array
*/
public function writeW10Wrap()
{
if (!is_null($this->w10wrap)) {
$this->xmlWriter->startElement('w10:wrap');
$this->xmlWriter->writeAttribute('type', $this->w10wrap);
$this->xmlWriter->endElement(); // w10:wrap
}
}
/**
* Get element style
*
* @return array
*/
private function getElementStyle()
{
$styles = array();
$styleValues = array(
'width' => $this->style->getWidth(),
'height' => $this->style->getHeight(),
'margin-top' => $this->style->getMarginTop(),
'margin-left' => $this->style->getMarginLeft()
);
foreach ($styleValues as $key => $value) {
if (!is_null($value) && $value != '') {
$styles[$key] = $value . 'px';
}
}
return $styles;
}
/**
* Assemble style array into style string
*
* @param array $styles
* @return string
*/
private function assembleStyle($styles = array())
{
$style = '';
foreach ($styles as $key => $value) {
if (!is_null($value) && $value != '') {
$style .= "{$key}:{$value}; ";
}
}
return trim($style);
}
}