* Moving wfGetSVGSize() and wfScaleSVGUnit() into a seperate SVGMetadataExtractor.
[lhc/web/wiklou.git] / includes / media / SVGMetadataExtractor.php
1 <?php
2 /**
3 * SVGMetadataExtractor.php
4 *
5 * @file
6 * @ingroup Media
7 */
8
9 class SVGMetadataExtractor {
10 static function getMetadata( $filename ) {
11 $filter = new XmlSizeFilter();
12 $xml = new XmlTypeCheck( $filename, array( $filter, 'filter' ) );
13 if( $xml->wellFormed ) {
14 return array(
15 'width' => $filter->width,
16 'height' => $filter->height
17 );
18 }
19 }
20 }
21
22 class XmlSizeFilter {
23 const DEFAULT_WIDTH = 512;
24 const DEFAULT_HEIGHT = 512;
25 var $first = true;
26 var $width = self::DEFAULT_WIDTH;
27 var $height = self::DEFAULT_HEIGHT;
28 function filter( $name, $attribs ) {
29 if( $this->first ) {
30 $defaultWidth = self::DEFAULT_WIDTH;
31 $defaultHeight = self::DEFAULT_HEIGHT;
32 $aspect = 1.0;
33 $width = null;
34 $height = null;
35
36 if( isset( $attribs['viewBox'] ) ) {
37 // min-x min-y width height
38 $viewBox = preg_split( '/\s+/', trim( $attribs['viewBox'] ) );
39 if( count( $viewBox ) == 4 ) {
40 $viewWidth = $this->scaleSVGUnit( $viewBox[2] );
41 $viewHeight = $this->scaleSVGUnit( $viewBox[3] );
42 if( $viewWidth > 0 && $viewHeight > 0 ) {
43 $aspect = $viewWidth / $viewHeight;
44 $defaultHeight = $defaultWidth / $aspect;
45 }
46 }
47 }
48 if( isset( $attribs['width'] ) ) {
49 $width = $this->scaleSVGUnit( $attribs['width'], $defaultWidth );
50 }
51 if( isset( $attribs['height'] ) ) {
52 $height = $this->scaleSVGUnit( $attribs['height'], $defaultHeight );
53 }
54
55 if( !isset( $width ) && !isset( $height ) ) {
56 $width = $defaultWidth;
57 $height = $width / $aspect;
58 } elseif( isset( $width ) && !isset( $height ) ) {
59 $height = $width / $aspect;
60 } elseif( isset( $height ) && !isset( $width ) ) {
61 $width = $height * $aspect;
62 }
63
64 if( $width > 0 && $height > 0 ) {
65 $this->width = intval( round( $width ) );
66 $this->height = intval( round( $height ) );
67 }
68
69 $this->first = false;
70 }
71 }
72
73 /**
74 * Return a rounded pixel equivalent for a labeled CSS/SVG length.
75 * http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers
76 *
77 * @param $length String: CSS/SVG length.
78 * @param $viewportSize: Float optional scale for percentage units...
79 * @return float: length in pixels
80 */
81 function scaleSVGUnit( $length, $viewportSize=512 ) {
82 static $unitLength = array(
83 'px' => 1.0,
84 'pt' => 1.25,
85 'pc' => 15.0,
86 'mm' => 3.543307,
87 'cm' => 35.43307,
88 'in' => 90.0,
89 'em' => 16.0, // fake it?
90 'ex' => 12.0, // fake it?
91 '' => 1.0, // "User units" pixels by default
92 );
93 $matches = array();
94 if( preg_match( '/^\s*(\d+(?:\.\d+)?)(em|ex|px|pt|pc|cm|mm|in|%|)\s*$/', $length, $matches ) ) {
95 $length = floatval( $matches[1] );
96 $unit = $matches[2];
97 if( $unit == '%' ) {
98 return $length * 0.01 * $viewportSize;
99 } else {
100 return $length * $unitLength[$unit];
101 }
102 } else {
103 // Assume pixels
104 return floatval( $length );
105 }
106 }
107 }