Skip to content

Commit 02508f2

Browse files
committed
Conversion of arbitrary absolute CSS units
- utility functions to parse lengths given in absolute CSS units (in. px, mm, cm, pc)
1 parent 4decaff commit 02508f2

File tree

2 files changed

+197
-0
lines changed

2 files changed

+197
-0
lines changed

src/PhpWord/Shared/Converter.php

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
namespace PhpOffice\PhpWord\Shared;
1919

20+
use PhpOffice\PhpWord\Exception\InvalidStyleException;
21+
2022
/**
2123
* Common converter functions
2224
*/
@@ -227,6 +229,121 @@ public static function emuToPixel($emu = 1)
227229
return round($emu / self::PIXEL_TO_EMU);
228230
}
229231

232+
/**
233+
* Convert an absolute CSS measurement to pixels
234+
*
235+
* Units for absolute CSS measurements are cm, mm, in, px, pt and pc
236+
*
237+
* Note that the result will be rounded to the nearest pixel
238+
*
239+
* @param string $cssMeasurement If no measurement unit is included then cm
240+
* is assumed
241+
*
242+
* @throws \PHPOffice\PhpWord\Exception\InvalidStyleException
243+
*
244+
* @return float
245+
*/
246+
public static function cssToPixel($cssMeasurement = '1cm')
247+
{
248+
$units = trim(preg_replace('/^-?(?:\\d+\\.\\d+|\\.?\\d+)/', '', trim($cssMeasurement)));
249+
$value = preg_replace('/\\D+$/', '', trim($cssMeasurement));
250+
if ((strlen($value) > 0) && ($value[0] == '.')) {
251+
$value = '0' . $value;
252+
}
253+
switch (strtolower($units)) {
254+
case 'in':
255+
$pixel = $value * static::INCH_TO_PIXEL;
256+
break;
257+
case 'cm':
258+
case '':
259+
$pixel = ($value / static::INCH_TO_CM) * static::INCH_TO_PIXEL;
260+
break;
261+
case 'mm':
262+
$pixel = ($value / (10 * static::INCH_TO_CM)) * static::INCH_TO_PIXEL;
263+
break;
264+
case 'pt':
265+
$pixel = ($value / static::INCH_TO_POINT) * static::INCH_TO_PIXEL;
266+
break;
267+
case 'pc':
268+
$pixel = ($value / (12 * static::INCH_TO_POINT)) * static::INCH_TO_PIXEL;
269+
break;
270+
case 'px':
271+
$pixel = floatval($value);
272+
break;
273+
default:
274+
throw new InvalidStyleException($cssMeasurement . ' is an unsupported CSS measurement');
275+
}
276+
return $pixel;
277+
}
278+
279+
/**
280+
* Convert an absolute CSS measurement to EMU
281+
*
282+
* Units for absolute CSS measurements are cm, mm, in, px, pt and pc
283+
*
284+
* @param string $cssMeasurement If no measurement unit is included then cm
285+
* is assumed
286+
*
287+
* @throws \PHPOffice\PhpWord\Exception\InvalidStyleException
288+
*
289+
* @return float
290+
*/
291+
public static function cssToEmu($cssMeasurement = '1cm')
292+
{
293+
return static::cssToPixel($cssMeasurement) * static::PIXEL_TO_EMU;
294+
}
295+
296+
/**
297+
* Convert an absolute CSS measurement to point
298+
*
299+
* Units for absolute CSS measurements are cm, mm, in, px, pt and pc
300+
*
301+
* @param string $cssMeasurement If no measurement unit is included then cm
302+
* is assumed
303+
*
304+
* @throws \PHPOffice\PhpWord\Exception\InvalidStyleException
305+
*
306+
* @return float
307+
*/
308+
public static function cssToPoint($cssMeasurement = '1cm')
309+
{
310+
return static::cssToPixel($cssMeasurement) * static::INCH_TO_POINT / static::INCH_TO_PIXEL;
311+
}
312+
313+
/**
314+
* Convert an absolute CSS measurement to twip
315+
*
316+
* Units for absolute CSS measurements are cm, mm, in, px, pt and pc
317+
*
318+
* @param string $cssMeasurement If no measurement unit is included then cm
319+
* is assumed
320+
*
321+
* @throws \PHPOffice\PhpWord\Exception\InvalidStyleException
322+
*
323+
* @return float
324+
*/
325+
public static function cssToTwip($cssMeasurement = '1cm')
326+
{
327+
return static::cssToPixel($cssMeasurement) * static::INCH_TO_TWIP / static::INCH_TO_PIXEL;
328+
}
329+
330+
/**
331+
* Convert an absolute CSS measurement to centimeter
332+
*
333+
* Units for absolute CSS measurements are cm, mm, in, px, pt and pc
334+
*
335+
* @param string $cssMeasurement If no measurement unit is included then cm
336+
* is assumed
337+
*
338+
* @throws \PHPOffice\PhpWord\Exception\InvalidStyleException
339+
*
340+
* @return float
341+
*/
342+
public static function cssToCm($cssMeasurement = '1cm')
343+
{
344+
return static::cssToPixel($cssMeasurement) * static::INCH_TO_CM / static::INCH_TO_PIXEL;
345+
}
346+
230347
/**
231348
* Convert degree to angle
232349
*

tests/PhpWord/Shared/ConverterTest.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,84 @@ public function testHtmlToRGB()
112112
$this->assertEquals($value[1], $result);
113113
}
114114
}
115+
116+
/**
117+
* @covers ::cssToPixel
118+
* @test
119+
*/
120+
public function testCssToPixel()
121+
{
122+
// Prepare test values [ original, expected ]
123+
$values[] = array('1pt', (1 / 72) * 96);
124+
$values[] = array('10.5pc', (10.5 / (72 * 12)) * 96);
125+
$values[] = array('4cm', (4 / 2.54) * 96);
126+
$values[] = array('1', (1 / 2.54) * 96);
127+
$values[] = array('2mm', (0.2 / 2.54) * 96);
128+
$values[] = array('.1', (0.1 / 2.54) * 96);
129+
$values[] = array('2in', 2 * 96);
130+
foreach ($values as $value) {
131+
$result = Converter::cssToPixel($value[0]);
132+
$this->assertEquals($value[1], $result);
133+
}
134+
}
135+
136+
/**
137+
* @covers ::cssToEmu
138+
* @test
139+
*/
140+
public function testCssToEmu()
141+
{
142+
// Prepare test values [ original, expected ]
143+
$values[] = array('1pt', (1 / 72) * 96 * 9525);
144+
$values[] = array('10.5pc', (10.5 / (72 * 12)) * 96 * 9525);
145+
$values[] = array('4cm', (4 / 2.54) * 96 * 9525);
146+
$values[] = array('1', (1 / 2.54) * 96 * 9525);
147+
$values[] = array('2mm', (0.2 / 2.54) * 96 * 9525);
148+
$values[] = array('.1', (0.1 / 2.54) * 96 * 9525);
149+
$values[] = array('2in', 2 * 96 * 9525);
150+
foreach ($values as $value) {
151+
$result = Converter::cssToEmu($value[0]);
152+
$this->assertEquals($value[1], $result);
153+
}
154+
}
155+
156+
/**
157+
* @covers ::cssToCm
158+
* @test
159+
*/
160+
public function testCssToCm()
161+
{
162+
// Prepare test values [ original, expected ]
163+
$values[] = array('1pt', (1 / 72) * 2.54);
164+
$values[] = array('10.5pc', (10.5 / (72 * 12)) * 2.54);
165+
$values[] = array('4cm', 4);
166+
$values[] = array('1', 1);
167+
$values[] = array('2mm', 2 / 10);
168+
$values[] = array('.1', 1 / 10);
169+
$values[] = array('2in', 2 * 2.54);
170+
foreach ($values as $value) {
171+
$result = Converter::cssToCm($value[0]);
172+
$this->assertEquals($value[1], $result);
173+
}
174+
}
175+
176+
/**
177+
* @covers ::cssToTwip
178+
* @test
179+
*/
180+
public function testCssToTwip()
181+
{
182+
// Prepare test values [ original, expected ]
183+
$values[] = array('1pt', (1 / 72) * 1440);
184+
$values[] = array('10.5pc', (10.5 / (72 * 12)) * 1440);
185+
$values[] = array('4cm', (4 / 2.54) * 1440);
186+
$values[] = array('1', (1 / 2.54) * 1440);
187+
$values[] = array('2mm', (0.2 / 2.54) * 1440);
188+
$values[] = array('.1', (0.1 / 2.54) * 1440);
189+
$values[] = array('2in', 2 * 1440);
190+
foreach ($values as $value) {
191+
$result = Converter::cssToTwip($value[0]);
192+
$this->assertEquals($value[1], $result);
193+
}
194+
}
115195
}

0 commit comments

Comments
 (0)