r75847 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r75846‎ | r75847 | r75848 >
Date:23:57, 1 November 2010
Author:hartman
Status:ok
Tags:
Comment:
* Moving wfGetSVGSize() and wfScaleSVGUnit() into a seperate SVGMetadataExtractor.
* SVG metadata is now stored and versioned.

Chosing not to provide fallback for these functions as they seem unused outside of SVG.php (per Google) and grep.
Modified paths:
  • /trunk/phase3/includes/AutoLoader.php (modified) (history)
  • /trunk/phase3/includes/ImageFunctions.php (modified) (history)
  • /trunk/phase3/includes/media/SVG.php (modified) (history)
  • /trunk/phase3/includes/media/SVGMetadataExtractor.php (added) (history)

Diff [purge]

Index: trunk/phase3/includes/media/SVGMetadataExtractor.php
@@ -0,0 +1,107 @@
 2+<?php
 3+/**
 4+ * SVGMetadataExtractor.php
 5+ *
 6+ * @file
 7+ * @ingroup Media
 8+ */
 9+
 10+class SVGMetadataExtractor {
 11+ static function getMetadata( $filename ) {
 12+ $filter = new XmlSizeFilter();
 13+ $xml = new XmlTypeCheck( $filename, array( $filter, 'filter' ) );
 14+ if( $xml->wellFormed ) {
 15+ return array(
 16+ 'width' => $filter->width,
 17+ 'height' => $filter->height
 18+ );
 19+ }
 20+ }
 21+}
 22+
 23+class XmlSizeFilter {
 24+ const DEFAULT_WIDTH = 512;
 25+ const DEFAULT_HEIGHT = 512;
 26+ var $first = true;
 27+ var $width = self::DEFAULT_WIDTH;
 28+ var $height = self::DEFAULT_HEIGHT;
 29+ function filter( $name, $attribs ) {
 30+ if( $this->first ) {
 31+ $defaultWidth = self::DEFAULT_WIDTH;
 32+ $defaultHeight = self::DEFAULT_HEIGHT;
 33+ $aspect = 1.0;
 34+ $width = null;
 35+ $height = null;
 36+
 37+ if( isset( $attribs['viewBox'] ) ) {
 38+ // min-x min-y width height
 39+ $viewBox = preg_split( '/\s+/', trim( $attribs['viewBox'] ) );
 40+ if( count( $viewBox ) == 4 ) {
 41+ $viewWidth = $this->scaleSVGUnit( $viewBox[2] );
 42+ $viewHeight = $this->scaleSVGUnit( $viewBox[3] );
 43+ if( $viewWidth > 0 && $viewHeight > 0 ) {
 44+ $aspect = $viewWidth / $viewHeight;
 45+ $defaultHeight = $defaultWidth / $aspect;
 46+ }
 47+ }
 48+ }
 49+ if( isset( $attribs['width'] ) ) {
 50+ $width = $this->scaleSVGUnit( $attribs['width'], $defaultWidth );
 51+ }
 52+ if( isset( $attribs['height'] ) ) {
 53+ $height = $this->scaleSVGUnit( $attribs['height'], $defaultHeight );
 54+ }
 55+
 56+ if( !isset( $width ) && !isset( $height ) ) {
 57+ $width = $defaultWidth;
 58+ $height = $width / $aspect;
 59+ } elseif( isset( $width ) && !isset( $height ) ) {
 60+ $height = $width / $aspect;
 61+ } elseif( isset( $height ) && !isset( $width ) ) {
 62+ $width = $height * $aspect;
 63+ }
 64+
 65+ if( $width > 0 && $height > 0 ) {
 66+ $this->width = intval( round( $width ) );
 67+ $this->height = intval( round( $height ) );
 68+ }
 69+
 70+ $this->first = false;
 71+ }
 72+ }
 73+
 74+ /**
 75+ * Return a rounded pixel equivalent for a labeled CSS/SVG length.
 76+ * http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers
 77+ *
 78+ * @param $length String: CSS/SVG length.
 79+ * @param $viewportSize: Float optional scale for percentage units...
 80+ * @return float: length in pixels
 81+ */
 82+ function scaleSVGUnit( $length, $viewportSize=512 ) {
 83+ static $unitLength = array(
 84+ 'px' => 1.0,
 85+ 'pt' => 1.25,
 86+ 'pc' => 15.0,
 87+ 'mm' => 3.543307,
 88+ 'cm' => 35.43307,
 89+ 'in' => 90.0,
 90+ 'em' => 16.0, // fake it?
 91+ 'ex' => 12.0, // fake it?
 92+ '' => 1.0, // "User units" pixels by default
 93+ );
 94+ $matches = array();
 95+ if( preg_match( '/^\s*(\d+(?:\.\d+)?)(em|ex|px|pt|pc|cm|mm|in|%|)\s*$/', $length, $matches ) ) {
 96+ $length = floatval( $matches[1] );
 97+ $unit = $matches[2];
 98+ if( $unit == '%' ) {
 99+ return $length * 0.01 * $viewportSize;
 100+ } else {
 101+ return $length * $unitLength[$unit];
 102+ }
 103+ } else {
 104+ // Assume pixels
 105+ return floatval( $length );
 106+ }
 107+ }
 108+}
Property changes on: trunk/phase3/includes/media/SVGMetadataExtractor.php
___________________________________________________________________
Added: svn:eol-style
1109 + native
Index: trunk/phase3/includes/media/SVG.php
@@ -12,6 +12,8 @@
1313 * @ingroup Media
1414 */
1515 class SvgHandler extends ImageHandler {
 16+ const SVG_METADATA_VERSION = 1;
 17+
1618 function isEnabled() {
1719 global $wgSVGConverters, $wgSVGConverter;
1820 if ( !isset( $wgSVGConverters[$wgSVGConverter] ) ) {
@@ -30,6 +32,11 @@
3133 return true;
3234 }
3335
 36+ function isAnimatedImage( $image ) {
 37+ # TODO: detect animated SVGs
 38+ return false;
 39+ }
 40+
3441 function normaliseParams( $image, &$params ) {
3542 global $wgSVGMaxSize;
3643 if ( !parent::normaliseParams( $image, $params ) ) {
@@ -111,8 +118,16 @@
112119 return true;
113120 }
114121
115 - function getImageSize( $image, $path ) {
116 - return wfGetSVGsize( $path );
 122+ function getImageSize( $file, $path, $metadata = false ) {
 123+ if ( $metadata === false ) {
 124+ $metadata = $file->getMetaData();
 125+ }
 126+ $metadata = $this->unpackMetaData( $metadata );
 127+
 128+ if ( isset( $metadata['width'] ) && isset( $metadata['height'] ) ) {
 129+ return array( $metadata['width'], $metadata['height'], 'SVG',
 130+ "width=\"{$metadata['width']}\" height=\"{$metadata['height']}\"" );
 131+ }
117132 }
118133
119134 function getThumbType( $ext, $mime, $params = null ) {
@@ -126,4 +141,38 @@
127142 $wgLang->formatNum( $file->getHeight() ),
128143 $wgLang->formatSize( $file->getSize() ) );
129144 }
 145+
 146+ function formatMetadata( $file ) {
 147+ return false;
 148+ }
 149+
 150+ function getMetadata( $file, $filename ) {
 151+ $metadata = array();
 152+ try {
 153+ $metadata = SVGMetadataExtractor::getMetadata( $filename );
 154+ } catch( Exception $e ) {
 155+ // Broken file?
 156+ wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
 157+ return '0';
 158+ }
 159+ $metadata['version'] = self::SVG_METADATA_VERSION;
 160+ return serialize( $metadata );
 161+ }
 162+
 163+ function unpackMetadata( $metadata ) {
 164+ $unser = @unserialize( $metadata );
 165+ if ( isset( $unser['version'] ) && $unser['version'] == self::SVG_METADATA_VERSION ) {
 166+ return $unser;
 167+ } else {
 168+ return false;
 169+ }
 170+ }
 171+
 172+ function getMetadataType( $image ) {
 173+ return 'parsed-svg';
 174+ }
 175+
 176+ function isMetadataValid( $image, $metadata ) {
 177+ return $this->unpackMetadata( $metadata ) !== false;
 178+ }
130179 }
Index: trunk/phase3/includes/AutoLoader.php
@@ -483,6 +483,7 @@
484484 'PNGHandler' => 'includes/media/PNG.php',
485485 'PNGMetadataExtractor' => 'includes/media/PNGMetadataExtractor.php',
486486 'SvgHandler' => 'includes/media/SVG.php',
 487+ 'SVGMetadataExtractor' => 'includes/media/SVGMetadataExtractor.php',
487488 'ThumbnailImage' => 'includes/media/MediaTransformOutput.php',
488489 'TiffHandler' => 'includes/media/Tiff.php',
489490 'TransformParameterError' => 'includes/media/MediaTransformOutput.php',
Index: trunk/phase3/includes/ImageFunctions.php
@@ -6,113 +6,6 @@
77 */
88
99 /**
10 - * Return a rounded pixel equivalent for a labeled CSS/SVG length.
11 - * http://www.w3.org/TR/SVG11/coords.html#UnitIdentifiers
12 - *
13 - * @param $length String: CSS/SVG length.
14 - * @param $viewportSize: Float optional scale for percentage units...
15 - * @return float: length in pixels
16 - */
17 -function wfScaleSVGUnit( $length, $viewportSize=512 ) {
18 - static $unitLength = array(
19 - 'px' => 1.0,
20 - 'pt' => 1.25,
21 - 'pc' => 15.0,
22 - 'mm' => 3.543307,
23 - 'cm' => 35.43307,
24 - 'in' => 90.0,
25 - 'em' => 16.0, // fake it?
26 - 'ex' => 12.0, // fake it?
27 - '' => 1.0, // "User units" pixels by default
28 - );
29 - $matches = array();
30 - if( preg_match( '/^\s*(\d+(?:\.\d+)?)(em|ex|px|pt|pc|cm|mm|in|%|)\s*$/', $length, $matches ) ) {
31 - $length = floatval( $matches[1] );
32 - $unit = $matches[2];
33 - if( $unit == '%' ) {
34 - return $length * 0.01 * $viewportSize;
35 - } else {
36 - return $length * $unitLength[$unit];
37 - }
38 - } else {
39 - // Assume pixels
40 - return floatval( $length );
41 - }
42 -}
43 -
44 -class XmlSizeFilter {
45 - const DEFAULT_WIDTH = 512;
46 - const DEFAULT_HEIGHT = 512;
47 - var $first = true;
48 - var $width = self::DEFAULT_WIDTH;
49 - var $height = self::DEFAULT_HEIGHT;
50 - function filter( $name, $attribs ) {
51 - if( $this->first ) {
52 - $defaultWidth = self::DEFAULT_WIDTH;
53 - $defaultHeight = self::DEFAULT_HEIGHT;
54 - $aspect = 1.0;
55 - $width = null;
56 - $height = null;
57 -
58 - if( isset( $attribs['viewBox'] ) ) {
59 - // min-x min-y width height
60 - $viewBox = preg_split( '/\s+/', trim( $attribs['viewBox'] ) );
61 - if( count( $viewBox ) == 4 ) {
62 - $viewWidth = wfScaleSVGUnit( $viewBox[2] );
63 - $viewHeight = wfScaleSVGUnit( $viewBox[3] );
64 - if( $viewWidth > 0 && $viewHeight > 0 ) {
65 - $aspect = $viewWidth / $viewHeight;
66 - $defaultHeight = $defaultWidth / $aspect;
67 - }
68 - }
69 - }
70 - if( isset( $attribs['width'] ) ) {
71 - $width = wfScaleSVGUnit( $attribs['width'], $defaultWidth );
72 - }
73 - if( isset( $attribs['height'] ) ) {
74 - $height = wfScaleSVGUnit( $attribs['height'], $defaultHeight );
75 - }
76 -
77 - if( !isset( $width ) && !isset( $height ) ) {
78 - $width = $defaultWidth;
79 - $height = $width / $aspect;
80 - } elseif( isset( $width ) && !isset( $height ) ) {
81 - $height = $width / $aspect;
82 - } elseif( isset( $height ) && !isset( $width ) ) {
83 - $width = $height * $aspect;
84 - }
85 -
86 - if( $width > 0 && $height > 0 ) {
87 - $this->width = intval( round( $width ) );
88 - $this->height = intval( round( $height ) );
89 - }
90 -
91 - $this->first = false;
92 - }
93 - }
94 -}
95 -
96 -/**
97 - * Compatible with PHP getimagesize()
98 - * @todo support gzipped SVGZ
99 - * @todo check XML more carefully
100 - * @todo sensible defaults
101 - *
102 - * @param $filename String: full name of the file (passed to php fopen()).
103 - * @return array
104 - */
105 -function wfGetSVGsize( $filename ) {
106 - $filter = new XmlSizeFilter();
107 - $xml = new XmlTypeCheck( $filename, array( $filter, 'filter' ) );
108 - if( $xml->wellFormed ) {
109 - return array( $filter->width, $filter->height, 'SVG',
110 - "width=\"$filter->width\" height=\"$filter->height\"" );
111 - }
112 -
113 - return false;
114 -}
115 -
116 -/**
11710 * Determine if an image exists on the 'bad image list'.
11811 *
11912 * The format of MediaWiki:Bad_image_list is as follows:

Status & tagging log