- // Recurse into children of current tag, looking for animation and languages.
- $this->animateFilterAndLang( $tag );
- }
-
- // Goto next element, which is sibling of current (Skip children).
- $keepReading = $this->reader->next();
- }
-
- $this->reader->close();
-
- $this->metadata['translations'] = $this->languages + $this->languagePrefixes;
-
- return true;
- }
-
- /**
- * Read a textelement from an element
- *
- * @param string $name Name of the element that we are reading from
- * @param string $metafield Field that we will fill with the result
- */
- private function readField( $name, $metafield = null ) {
- $this->debug( "Read field $metafield" );
- if ( !$metafield || $this->reader->nodeType != XMLReader::ELEMENT ) {
- return;
- }
- $keepReading = $this->reader->read();
- while ( $keepReading ) {
- if ( $this->reader->localName == $name
- && $this->reader->namespaceURI == self::NS_SVG
- && $this->reader->nodeType == XMLReader::END_ELEMENT
- ) {
- break;
- } elseif ( $this->reader->nodeType == XMLReader::TEXT ) {
- $this->metadata[$metafield] = trim( $this->reader->value );
- }
- $keepReading = $this->reader->read();
- }
- }
-
- /**
- * Read an XML snippet from an element
- *
- * @param string $metafield Field that we will fill with the result
- * @throws MWException
- */
- private function readXml( $metafield = null ) {
- $this->debug( "Read top level metadata" );
- if ( !$metafield || $this->reader->nodeType != XMLReader::ELEMENT ) {
- return;
- }
- // @todo Find and store type of xml snippet. metadata['metadataType'] = "rdf"
- $this->metadata[$metafield] = trim( $this->reader->readInnerXml() );
-
- $this->reader->next();
- }
-
- /**
- * Filter all children, looking for animated elements.
- * Also get a list of languages that can be targeted.
- *
- * @param string $name Name of the element that we are reading from
- */
- private function animateFilterAndLang( $name ) {
- $this->debug( "animate filter for tag $name" );
- if ( $this->reader->nodeType != XMLReader::ELEMENT ) {
- return;
- }
- if ( $this->reader->isEmptyElement ) {
- return;
- }
- $exitDepth = $this->reader->depth;
- $keepReading = $this->reader->read();
- while ( $keepReading ) {
- if ( $this->reader->localName == $name && $this->reader->depth <= $exitDepth
- && $this->reader->nodeType == XMLReader::END_ELEMENT
- ) {
- break;
- } elseif ( $this->reader->namespaceURI == self::NS_SVG
- && $this->reader->nodeType == XMLReader::ELEMENT
- ) {
- $sysLang = $this->reader->getAttribute( 'systemLanguage' );
- if ( !is_null( $sysLang ) && $sysLang !== '' ) {
- // See https://www.w3.org/TR/SVG/struct.html#SystemLanguageAttribute
- $langList = explode( ',', $sysLang );
- foreach ( $langList as $langItem ) {
- $langItem = trim( $langItem );
- if ( Language::isWellFormedLanguageTag( $langItem ) ) {
- $this->languages[$langItem] = self::LANG_FULL_MATCH;
- }
- // Note, the standard says that any prefix should work,
- // here we do only the initial prefix, since that will catch
- // 99% of cases, and we are going to compare against fallbacks.
- // This differs mildly from how the spec says languages should be
- // handled, however it matches better how the MediaWiki language
- // preference is generally handled.
- $dash = strpos( $langItem, '-' );
- // Intentionally checking both !false and > 0 at the same time.
- if ( $dash ) {
- $itemPrefix = substr( $langItem, 0, $dash );
- if ( Language::isWellFormedLanguageTag( $itemPrefix ) ) {
- $this->languagePrefixes[$itemPrefix] = self::LANG_PREFIX_MATCH;
- }
- }
- }
- }
- switch ( $this->reader->localName ) {
- case 'script':
- // Normally we disallow files with
- // <script>, but its possible
- // to configure MW to disable
- // such checks.
- case 'animate':
- case 'set':
- case 'animateMotion':
- case 'animateColor':
- case 'animateTransform':
- $this->debug( "HOUSTON WE HAVE ANIMATION" );
- $this->metadata['animated'] = true;
- break;
- }
- }
- $keepReading = $this->reader->read();
- }
- }
-
- private function debug( $data ) {
- if ( $this->mDebug ) {
- wfDebug( "SVGReader: $data\n" );
- }
- }
-
- /**
- * Parse the attributes of an SVG element
- *
- * The parser has to be in the start element of "<svg>"
- */
- private function handleSVGAttribs() {
- $defaultWidth = self::DEFAULT_WIDTH;
- $defaultHeight = self::DEFAULT_HEIGHT;
- $aspect = 1.0;
- $width = null;
- $height = null;
-
- if ( $this->reader->getAttribute( 'viewBox' ) ) {
- // min-x min-y width height
- $viewBox = preg_split( '/\s*[\s,]\s*/', trim( $this->reader->getAttribute( 'viewBox' ) ) );
- if ( count( $viewBox ) == 4 ) {
- $viewWidth = $this->scaleSVGUnit( $viewBox[2] );
- $viewHeight = $this->scaleSVGUnit( $viewBox[3] );
- if ( $viewWidth > 0 && $viewHeight > 0 ) {
- $aspect = $viewWidth / $viewHeight;
- $defaultHeight = $defaultWidth / $aspect;
- }
- }
- }
- if ( $this->reader->getAttribute( 'width' ) ) {
- $width = $this->scaleSVGUnit( $this->reader->getAttribute( 'width' ), $defaultWidth );
- $this->metadata['originalWidth'] = $this->reader->getAttribute( 'width' );
- }
- if ( $this->reader->getAttribute( 'height' ) ) {
- $height = $this->scaleSVGUnit( $this->reader->getAttribute( 'height' ), $defaultHeight );
- $this->metadata['originalHeight'] = $this->reader->getAttribute( 'height' );
- }
-
- if ( !isset( $width ) && !isset( $height ) ) {
- $width = $defaultWidth;
- $height = $width / $aspect;
- } elseif ( isset( $width ) && !isset( $height ) ) {
- $height = $width / $aspect;
- } elseif ( isset( $height ) && !isset( $width ) ) {
- $width = $height * $aspect;
- }
-
- if ( $width > 0 && $height > 0 ) {
- $this->metadata['width'] = intval( round( $width ) );
- $this->metadata['height'] = intval( round( $height ) );
- }
- }