X-Git-Url: https://git.cyclocoop.org/%27.WWW_URL.%27admin/?a=blobdiff_plain;f=includes%2Fmedia%2FSVG.php;h=9a32cf6e17b82fac2e0abe7989d9b8776a9f8526;hb=3b906b320ef2abdd103956c2b7a8f9b8604a244d;hp=f0519e8973a84e8c85f5f411580d48712281c54d;hpb=e240272a80d384bd3d4785f53c92ddf5cac8b52b;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/media/SVG.php b/includes/media/SVG.php index f0519e8973..9a32cf6e17 100644 --- a/includes/media/SVG.php +++ b/includes/media/SVG.php @@ -1,13 +1,19 @@ getMetadata(); + if ( $metadata ) { + $metadata = $this->unpackMetadata( $metadata ); + if( isset( $metadata['animated'] ) ) { + return $metadata['animated']; + } + } + return false; + } + + /** + * @param $image File + * @param $params + * @return bool + */ function normaliseParams( $image, &$params ) { global $wgSVGMaxSize; if ( !parent::normaliseParams( $image, $params ) ) { return false; } - # Don't make an image bigger than wgMaxSVGSize - $params['physicalWidth'] = $params['width']; - $params['physicalHeight'] = $params['height']; - if ( $params['physicalWidth'] > $wgSVGMaxSize ) { - $srcWidth = $image->getWidth( $params['page'] ); - $srcHeight = $image->getHeight( $params['page'] ); - $params['physicalWidth'] = $wgSVGMaxSize; - $params['physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight, $wgSVGMaxSize ); + # Don't make an image bigger than wgMaxSVGSize on the smaller side + if ( $params['physicalWidth'] <= $params['physicalHeight'] ) { + if ( $params['physicalWidth'] > $wgSVGMaxSize ) { + $srcWidth = $image->getWidth( $params['page'] ); + $srcHeight = $image->getHeight( $params['page'] ); + $params['physicalWidth'] = $wgSVGMaxSize; + $params['physicalHeight'] = File::scaleHeight( $srcWidth, $srcHeight, $wgSVGMaxSize ); + } + } else { + if ( $params['physicalHeight'] > $wgSVGMaxSize ) { + $srcWidth = $image->getWidth( $params['page'] ); + $srcHeight = $image->getHeight( $params['page'] ); + $params['physicalWidth'] = File::scaleHeight( $srcHeight, $srcWidth, $wgSVGMaxSize ); + $params['physicalHeight'] = $wgSVGMaxSize; + } } return true; } + /** + * @param $image File + * @param $dstPath + * @param $dstUrl + * @param $params + * @param int $flags + * @return bool|MediaTransformError|ThumbnailImage|TransformParameterError + */ function doTransform( $image, $dstPath, $dstUrl, $params, $flags = 0 ) { - global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath; - if ( !$this->normaliseParams( $image, $params ) ) { return new TransformParameterError( $params ); } @@ -55,11 +99,11 @@ class SvgHandler extends ImageHandler { return new ThumbnailImage( $image, $dstUrl, $clientWidth, $clientHeight, $dstPath ); } - if ( !wfMkdirParents( dirname( $dstPath ) ) ) { + if ( !wfMkdirParents( dirname( $dstPath ), null, __METHOD__ ) ) { return new MediaTransformError( 'thumbnail_error', $clientWidth, $clientHeight, wfMsg( 'thumbnail_dest_directory' ) ); } - + $status = $this->rasterize( $srcPath, $dstPath, $physicalWidth, $physicalHeight ); if( $status === true ) { return new ThumbnailImage( $image, $dstUrl, $clientWidth, $clientHeight, $dstPath ); @@ -67,8 +111,8 @@ class SvgHandler extends ImageHandler { return $status; // MediaTransformError } } - - /* + + /** * Transform an SVG file to PNG * This function can be called outside of thumbnail contexts * @param string $srcPath @@ -80,20 +124,34 @@ class SvgHandler extends ImageHandler { public function rasterize( $srcPath, $dstPath, $width, $height ) { global $wgSVGConverters, $wgSVGConverter, $wgSVGConverterPath; $err = false; + $retval = ''; if ( isset( $wgSVGConverters[$wgSVGConverter] ) ) { - $cmd = str_replace( - array( '$path/', '$width', '$height', '$input', '$output' ), - array( $wgSVGConverterPath ? wfEscapeShellArg( "$wgSVGConverterPath/" ) : "", - intval( $width ), - intval( $height ), - wfEscapeShellArg( $srcPath ), - wfEscapeShellArg( $dstPath ) ), - $wgSVGConverters[$wgSVGConverter] - ) . " 2>&1"; - wfProfileIn( 'rsvg' ); - wfDebug( __METHOD__.": $cmd\n" ); - $err = wfShellExec( $cmd, $retval ); - wfProfileOut( 'rsvg' ); + if ( is_array( $wgSVGConverters[$wgSVGConverter] ) ) { + // This is a PHP callable + $func = $wgSVGConverters[$wgSVGConverter][0]; + $args = array_merge( array( $srcPath, $dstPath, $width, $height ), + array_slice( $wgSVGConverters[$wgSVGConverter], 1 ) ); + if ( !is_callable( $func ) ) { + throw new MWException( "$func is not callable" ); + } + $err = call_user_func_array( $func, $args ); + $retval = (bool)$err; + } else { + // External command + $cmd = str_replace( + array( '$path/', '$width', '$height', '$input', '$output' ), + array( $wgSVGConverterPath ? wfEscapeShellArg( "$wgSVGConverterPath/" ) : "", + intval( $width ), + intval( $height ), + wfEscapeShellArg( $srcPath ), + wfEscapeShellArg( $dstPath ) ), + $wgSVGConverters[$wgSVGConverter] + ) . " 2>&1"; + wfProfileIn( 'rsvg' ); + wfDebug( __METHOD__.": $cmd\n" ); + $err = wfShellExec( $cmd, $retval ); + wfProfileOut( 'rsvg' ); + } } $removed = $this->removeBadFile( $dstPath, $retval ); if ( $retval != 0 || $removed ) { @@ -104,14 +162,46 @@ class SvgHandler extends ImageHandler { return true; } - function getImageSize( $image, $path ) { - return wfGetSVGsize( $path ); + public static function rasterizeImagickExt( $srcPath, $dstPath, $width, $height ) { + $im = new Imagick( $srcPath ); + $im->setImageFormat( 'png' ); + $im->setBackgroundColor( 'transparent' ); + $im->setImageDepth( 8 ); + + if ( !$im->thumbnailImage( intval( $width ), intval( $height ), /* fit */ false ) ) { + return 'Could not resize image'; + } + if ( !$im->writeImage( $dstPath ) ) { + return "Could not write to $dstPath"; + } } - function getThumbType( $ext, $mime ) { + /** + * @param $file File + * @param $path + * @param bool $metadata + * @return array + */ + function getImageSize( $file, $path, $metadata = false ) { + if ( $metadata === false ) { + $metadata = $file->getMetaData(); + } + $metadata = $this->unpackMetaData( $metadata ); + + if ( isset( $metadata['width'] ) && isset( $metadata['height'] ) ) { + return array( $metadata['width'], $metadata['height'], 'SVG', + "width=\"{$metadata['width']}\" height=\"{$metadata['height']}\"" ); + } + } + + function getThumbType( $ext, $mime, $params = null ) { return array( 'png', 'image/png' ); } + /** + * @param $file File + * @return string + */ function getLongDesc( $file ) { global $wgLang; return wfMsgExt( 'svg-long-desc', 'parseinline', @@ -119,4 +209,90 @@ class SvgHandler extends ImageHandler { $wgLang->formatNum( $file->getHeight() ), $wgLang->formatSize( $file->getSize() ) ); } + + function getMetadata( $file, $filename ) { + try { + $metadata = SVGMetadataExtractor::getMetadata( $filename ); + } catch( Exception $e ) { + // Broken file? + wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" ); + return '0'; + } + $metadata['version'] = self::SVG_METADATA_VERSION; + return serialize( $metadata ); + } + + function unpackMetadata( $metadata ) { + wfSuppressWarnings(); + $unser = unserialize( $metadata ); + wfRestoreWarnings(); + if ( isset( $unser['version'] ) && $unser['version'] == self::SVG_METADATA_VERSION ) { + return $unser; + } else { + return false; + } + } + + function getMetadataType( $image ) { + return 'parsed-svg'; + } + + function isMetadataValid( $image, $metadata ) { + return $this->unpackMetadata( $metadata ) !== false; + } + + function visibleMetadataFields() { + $fields = array( 'title', 'description', 'animated' ); + return $fields; + } + + /** + * @param $file File + * @return array|bool + */ + function formatMetadata( $file ) { + $result = array( + 'visible' => array(), + 'collapsed' => array() + ); + $metadata = $file->getMetadata(); + if ( !$metadata ) { + return false; + } + $metadata = $this->unpackMetadata( $metadata ); + if ( !$metadata ) { + return false; + } + unset( $metadata['version'] ); + unset( $metadata['metadata'] ); /* non-formatted XML */ + + /* TODO: add a formatter + $format = new FormatSVG( $metadata ); + $formatted = $format->getFormattedData(); + */ + + // Sort fields into visible and collapsed + $visibleFields = $this->visibleMetadataFields(); + + // Rename fields to be compatible with exif, so that + // the labels for these fields work. + $conversion = array( 'width' => 'imagewidth', + 'height' => 'imagelength', + 'description' => 'imagedescription', + 'title' => 'objectname', + ); + foreach ( $metadata as $name => $value ) { + $tag = strtolower( $name ); + if ( isset( $conversion[$tag] ) ) { + $tag = $conversion[$tag]; + } + self::addMeta( $result, + in_array( $tag, $visibleFields ) ? 'visible' : 'collapsed', + 'exif', + $tag, + $value + ); + } + return $result; + } }