Browse Source

Adding SVG MIME-Type icons and supporting code

Alan Hardman 3 years ago
parent
commit
a753755698

+ 30 - 81
app/controller/files.php

@@ -5,7 +5,7 @@ namespace Controller;
 class Files extends \Controller {
 
 	/**
-	 * Forces the framework to use the local filesystem cache method if possible
+	 * Force the framework to use the local filesystem cache method if possible
 	 */
 	protected function _useFileCache() {
 		$f3 = \Base::instance();
@@ -14,6 +14,7 @@ class Files extends \Controller {
 
 	/**
 	 * Send a file to the browser
+	 *
 	 * @param  string $file
 	 * @param  string $mime
 	 * @param  string $filename
@@ -48,6 +49,8 @@ class Files extends \Controller {
 	}
 
 	/**
+	 * GET /files/thumb/@size-@id.@format
+	 *
 	 * @param \Base $f3
 	 * @param array $params
 	 * @throws \Exception
@@ -62,11 +65,13 @@ class Files extends \Controller {
 		}
 
 		// Output cached image if one exists
-		$hash = $f3->hash($f3->get('VERB') . " " . $f3->get('URI')) . ".thm";
-		if($cache->exists($hash, $data)) {
-			header("Content-type: image/" . $params["format"]);
-			echo $data;
-			return;
+		if($f3->get("DEBUG") < 2) {
+			$hash = $f3->hash($f3->get('VERB') . " " . $f3->get('URI')) . ".thm";
+			if($cache->exists($hash, $data)) {
+				header("Content-type: image/" . $params["format"]);
+				echo $data;
+				return;
+			}
 		}
 
 		$file = new \Model\Issue\File();
@@ -77,83 +82,24 @@ class Files extends \Controller {
 			return;
 		}
 
-		$fg = 0x000000;
-		$bg = 0xFFFFFF;
-
 		// Generate thumbnail of image file
-		if(substr($file->content_type, 0, 6) == "image/") {
-			if(is_file($file->disk_filename)) {
-				$img = new \Helper\Image($file->disk_filename);
-				$hide_ext = true;
-			} else {
-				$protocol = isset($_SERVER["SERVER_PROTOCOL"]) ? $_SERVER["SERVER_PROTOCOL"] : "HTTP/1.0";
-				header($protocol . " 404 Not Found");
-				$img = new \Helper\Image("img/404.png");
-			}
-			$img->resize($params["size"], $params["size"]);
-
-			$fg = 0xFFFFFF;
-			$bg = 0x000000;
-		}
-
-		// Generate thumbnail of text contents
-		elseif(substr($file->content_type, 0, 5) == "text/") {
-
-			// Get first 2KB of file
-			$fh = fopen($file->disk_filename, "r");
-			$str = fread($fh, 2048);
-			fclose($fh);
-
-			// Replace tabs with spaces
-			$str = str_replace("\t", "  ", $str);
-
-			$img = new \Helper\Image();
-			$img->create($params["size"], $params["size"]);
-			$img->fill(0xFFFFFF);
-			$img->text($str, round(0.05 * $params["size"]), 0, round(0.03 * $params["size"]), round(0.03 * $params["size"]), 0x777777);
-
-			// Show file type icon if available
-			if($file->content_type == "text/csv" || $file->content_type == "text/tsv") {
-				$icon = new \Image("img/mime/table.png");
-				$img->overlay($icon);
-			}
-		}
-
-		// Generate thumbnail of MS Office document
-		elseif(extension_loaded("zip")
-			&& $file->content_type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document") {
-			$zip = zip_open($file->disk_filename);
-			while(($entry = zip_read($zip)) !== false) {
-				if(preg_match("/word\/media\/image[0-9]+\.(png|jpe?g|gif|bmp|dib)/i", zip_entry_name($entry))) {
-					$idata = zip_entry_read($entry, zip_entry_filesize($entry));
-					$img = new \Helper\Image();
-					$img->load($idata);
-					break;
-				}
-			}
-
-			if(!isset($img)) {
-				$img = new \Helper\Image("img/mime/base.png");
-			}
-			$img->resize($params["size"], $params["size"]);
-		}
-
-		// Use generic file icon if type is not supported
-		else {
-			$img = new \Helper\Image("img/mime/base.png");
-			$img->resize($params["size"], $params["size"]);
-		}
-
-		// Render file extension over image
-		if(empty($hide_ext)) {
-			$ext = strtoupper(pathinfo($file->disk_filename, PATHINFO_EXTENSION));
-			$img->text($ext, $params["size"]*0.125, 0, round(0.05 * $params["size"]), round(0.05 * $params["size"]), $bg);
-			$img->text($ext, $params["size"]*0.125, 0, round(0.05 * $params["size"]) - 1, round(0.05 * $params["size"]) - 1, $fg);
+		/* @todo: Replace with hacky imagefillrectangle and imagecopyresampled
+			code to render a nice _image.svg-style frame around the thumbnail */
+		if(is_file($file->disk_filename)) {
+			$img = new \Helper\Image($file->disk_filename);
+			$hide_ext = true;
+		} else {
+			header("Content-Type: image/svg+xml");
+			readfile("img/mime/96/_404.svg");
+			return;
 		}
+		$img->resize($params["size"], $params["size"]);
 
 		// Render and cache image
 		$data = $img->dump($params["format"]);
-		$cache->set($hash, $data, $f3->get("cache_expire.attachments"));
+		if($f3->get("DEBUG") < 2) {
+			$cache->set($hash, $data, $f3->get("cache_expire.attachments"));
+		}
 
 		// Output image
 		header("Content-type: image/" . $params["format"]);
@@ -162,6 +108,8 @@ class Files extends \Controller {
 	}
 
 	/**
+	 * GET /avatar/@size-@id.@format
+	 *
 	 * @param \Base $f3
 	 * @param array $params
 	 * @throws \Exception
@@ -197,6 +145,8 @@ class Files extends \Controller {
 	}
 
 	/**
+	 * GET /files/preview/@id
+	 *
 	 * @param \Base $f3
 	 * @param array $params
 	 * @throws \Exception
@@ -230,6 +180,8 @@ class Files extends \Controller {
 	}
 
 	/**
+	 * GET /files/@id/@name
+	 *
 	 * @param \Base $f3
 	 * @param array $params
 	 * @throws \Exception
@@ -248,9 +200,6 @@ class Files extends \Controller {
 			$file->content_type == "text/plain" ||
 			$file->content_type == "application/pdf"
 		) {
-			// Don't force download on image and plain text files
-			// Eventually I'd like to have previews of files some way (more than
-			// the existing thumbnails), but for now this is how we do it - Alan
 			$force = false;
 		}
 

+ 51 - 4
app/helper/image.php

@@ -4,14 +4,61 @@ namespace Helper;
 
 class Image extends \Image {
 
-	protected $last_data;
+	protected $lastData;
+
+	static $mimeMap = array(
+		"image" => array(
+			"image/jpeg",
+			"image/png",
+			"image/gif",
+			"image/bmp",
+		),
+		"text" => array(
+			// @todo: Use these values to generate text file thumbnails
+			"text/plain",
+			"text/tsv",
+			"text/csv",
+		),
+		"icon" => array(
+			"application/.*zip" => "_archive",
+			"image/.+" => "_image",
+			"application/x-photoshop" => "_image",
+			"application/.*pdf" => "pdf",
+			"text/[ct]sv" => "csv",
+			"text/.+" => "txt",
+			"application/vnd\.oasis\.opendocument\.graphics" => "odg",
+			"application/vnd\.oasis\.opendocument\.spreadsheet" => "ods",
+			"application/vnd\.oasis\.opendocument\.presentation" => "odp",
+			"application/vnd\.oasis\.opendocument\.text" => "odt",
+			"application/(msword|vnd\.(ms-word|openxmlformats-officedocument\.wordprocessingml.+))" => "doc",
+			"application/(msexcel|vnd\.(ms-excel|openxmlformats-officedocument\.spreadsheetml.+))" => "xls",
+			"application/(mspowerpoint|vnd\.(ms-powerpoint|openxmlformats-officedocument\.presentationml.+))" => "ppt",
+		)
+	);
+
+	/**
+	 * Get an icon name by MIME type
+	 *
+	 * Returns "_blank" when no icon matches
+	 *
+	 * @param  string $contentType
+	 * @return string
+	 */
+	static function mimeIcon($contentType) {
+		foreach (self::$mimeMap["icon"] as $regex=>$name) {
+			if (preg_match("@^" . $regex . "$@i", $contentType)) {
+				return $name;
+			}
+		}
+		return "_blank";
+	}
 
 	/**
 	 * Get the last GD return value, generally from imagettftext
-	 * @return mixed last_data
+	 * @return mixed lastData
 	 */
 	function getLastData() {
-		return $this->last_data;
+		return $this->lastData;
 	}
 
 	/**
@@ -70,7 +117,7 @@ class Image extends \Image {
 			);
 		}
 
-		$this->last_data = imagettftext($this->data, $size, $angle, $x, $y, $color_id, $font, $text);
+		$this->lastData = imagettftext($this->data, $size, $angle, $x, $y, $color_id, $font, $text);
 		return $this->save();
 	}
 

+ 19 - 0
app/view/blocks/file/thumb.html

@@ -0,0 +1,19 @@
+<li id="f-{{ @file.id }}" data-id="{{ @file.id }}"
+	data-name="{{ @file.filename | esc }}"
+	data-user="{{ @file.user_name | esc }}"
+	data-date="{{ date('M j, Y \a\t g:ia', $this->utc2local(strtotime(@file.created_date))) }}"
+	data-mime="{{ @file.content_type | esc }}"
+	data-size="{{ @file.filesize | formatFilesize }}">
+	<a class="file-attachment" href="{{ @BASE }}/files/{{ @file.id }}/{{ @file.filename | esc }}" target="_blank">
+		<check if="{{ in_array(@file.content_type, \Helper\Image::@mimeMap.image) }}">
+			<true>
+				<img src="{{ @BASE }}/files/thumb/96-{{ @file.id }}.png" srcset="{{ @BASE }}/files/thumb/192-{{ @file.id }}.png 2x" alt>
+			</true>
+			<false>
+				<img src="{{ @BASE }}/img/mime/96/{{ \Helper\Image::mimeIcon(@file.content_type) }}.svg" alt>
+			</false>
+		</check>
+		{{ @file.filename | esc }}
+	</a>
+	<button type="button" class="btn btn-xs btn-danger delete" title="{{ @dict.delete }}">&times;</button>
+</li>

+ 22 - 10
app/view/issues/single.html

@@ -202,13 +202,7 @@
 					<div class="tab-pane fade in active" id="files-tiles">
 						<ul class="list-inline file-list">
 							<repeat group="{{ @files }}" value="{{ @file }}">
-								<li class="has-popover" id="f-{{ @file.id }}" data-id="{{ @file.id }}" data-trigger="hover" data-html="true" data-content="<p>{{ @dict.uploaded_by }}: {{ @file.user_name | esc }}</p>{{ @file.filename | esc }}<br>{{ date('M j, Y \a\t g:ia', $this->utc2local(strtotime(@file.created_date))) }}<br>{{ @file.filesize | formatFilesize }}">
-									<a class="file-attachment" href="{{ @BASE }}/files/{{ @file.id }}/{{ @file.filename | esc }}" data-mime="{{ @file.content_type }}" target="_blank">
-										<img src="{{ @BASE }}/files/thumb/96-{{ @file.id }}.png" srcset="{{ @BASE }}/files/thumb/192-{{ @file.id }}.png 2x" alt><br>
-										{{ @file.filename | esc }}
-									</a>
-									<button type="button" class="btn btn-xs btn-danger delete" title="{{ @dict.delete }}">&times;</button>
-								</li>
+								<include href="blocks/file/thumb.html" />
 							</repeat>
 						</ul>
 					</div>
@@ -217,7 +211,7 @@
 							<table class="table table-striped table-condensed file-list">
 								<thead>
 									<tr>
-										<th data-sort="int">{{ @dict.cols.id }}</th>
+										<th></th>
 										<th data-sort="string">{{ @dict.file_name }}</th>
 										<th data-sort="string">{{ @dict.uploaded_by }}</th>
 										<th data-sort="int">{{ @dict.upload_date }}</th>
@@ -228,8 +222,10 @@
 								<tbody>
 									<repeat group="{{ @files }}" value="{{ @file }}">
 										<tr id="ft-{{ @file.id }}" data-id="{{ @file.id }}">
-											<td>{{ @file.id }}</td>
-											<td><a class="file-attachment" href="{{ @BASE }}/files/{{ @file.id }}/{{ @file.filename }}" data-mime="{{ @file.content_type }}" target="_blank">{{ @file.filename | esc }}</a></td>
+											<td data-sort-value="{{ @file.content_type | esc }}">
+												<img src="{{ @BASE }}/img/mime/16/{{ \Helper\Image::mimeIcon(@file.content_type) }}.svg" alt>
+											</td>
+											<td><a class="file-attachment" href="{{ @BASE }}/files/{{ @file.id }}/{{ @file.filename | esc }}" target="_blank">{{ @file.filename | esc }}</a></td>
 											<td>{{ @file.user_name | esc }}</td>
 											<td data-sort-value="{{ strtotime(@file.created_date) }}">{{ date('M j, Y \a\t g:ia', $this->utc2local(strtotime(@file.created_date))) }}</td>
 											<td data-sort-value="{{ @file.filesize }}">{{ @file.filesize | formatFilesize }}</td>
@@ -580,6 +576,22 @@ $(function() {
 		autoclose: true
 	});
 
+	// Add file thumbnail popovers
+	$('#files-tiles li').each(function() {
+		$el = $(this);
+		$el.popover({
+			trigger: 'hover',
+			html: true,
+			delay: {
+				show: 250,
+				hide: 50
+			},
+			container: 'body',
+			placement: 'auto right',
+			content: '<b>' + $el.attr('data-name') + '</b><br>' + $el.attr('data-user') + '<br>' + $el.attr('data-date') + '<br>' +$el.attr('data-size')
+		});
+	});
+
 	// Handle file deletion
 	$('.file-list').on('click', '.delete', function(e) {
 		var $file = $(this).parents('li, tr');

+ 10 - 0
css/style.css

@@ -194,7 +194,9 @@ select[multiple] {
 	white-space: nowrap;
 }
 .file-list li img {
+	display: block;
 	width: 96px;
+	height: 96px;
 }
 .file-list li .delete {
 	position: absolute;
@@ -205,6 +207,14 @@ select[multiple] {
 .file-list li:hover .delete {
 	visibility: visible;
 }
+.file-list th:first-child,
+.file-list td:first-child {
+	width: 26px;
+}
+.file-list td:first-child img {
+	width: 16px;
+	height: 16px;
+}
 
 .issue-list .closed {
 	text-decoration: line-through;

File diff suppressed because it is too large
+ 1 - 0
img/mime/16/_404.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/_archive.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/_audio.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/_blank.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/_code.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/_image.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/_video.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/csv.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/doc.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/odg.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/odp.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/ods.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/odt.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/pdf.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/ppt.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/txt.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/16/xls.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/_404.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/_archive.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/_audio.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/_blank.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/_code.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/_image.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/_video.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/csv.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/doc.svg


+ 302 - 0
img/mime/96/odg.svg

@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="96"
+   height="96"
+   id="svg4112"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="libreoffice-drawing.svg">
+  <defs
+     id="defs4114">
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient3977"
+       id="linearGradient3988"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(1.864865,0,0,2.3513513,3.2432527,-58.432409)"
+       x1="23.99999"
+       y1="5.5641499"
+       x2="23.99999"
+       y2="43" />
+    <linearGradient
+       id="linearGradient3977">
+      <stop
+         offset="0"
+         style="stop-color:#ffffff;stop-opacity:1;"
+         id="stop3979" />
+      <stop
+         id="stop3981"
+         style="stop-color:#ffffff;stop-opacity:0.23529412;"
+         offset="0.03626217" />
+      <stop
+         offset="0.95056331"
+         style="stop-color:#ffffff;stop-opacity:0.15686275;"
+         id="stop3983" />
+      <stop
+         offset="1"
+         style="stop-color:#ffffff;stop-opacity:0.39215687;"
+         id="stop3985" />
+    </linearGradient>
+    <radialGradient
+       r="18.000002"
+       fy="11.49049"
+       fx="14.239056"
+       cy="11.49049"
+       cx="14.239056"
+       gradientTransform="matrix(0,6.4286071,-10.748425,0,149.83212,-127.40021)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3144-4"
+       xlink:href="#linearGradient3846-5"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="2.9062471"
+       x2="-51.786404"
+       y1="53.623615"
+       x1="-51.786404"
+       gradientTransform="matrix(1.638063,0,0,1.8097726,119.84832,-53.533733)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3146-3"
+       xlink:href="#linearGradient3856-6"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient8265-821-176-38-919-66-249-48-321">
+      <stop
+         id="stop5601"
+         style="stop-color:#ffffff;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop5603"
+         style="stop-color:#ffffff;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       y2="24.627615"
+       x2="20.054544"
+       y1="15.298182"
+       x1="16.626165"
+       gradientTransform="matrix(1.480272,0,0,2.7868792,12.473467,-62.634185)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient3051"
+       xlink:href="#linearGradient8265-821-176-38-919-66-249-48-321"
+       inkscape:collect="always" />
+    <linearGradient
+       y2="609.50507"
+       x2="302.85715"
+       y1="366.64789"
+       x1="302.85715"
+       gradientTransform="matrix(0.14476034,0,0,0.02053005,-4.3728904,1036.6837)"
+       gradientUnits="userSpaceOnUse"
+       id="linearGradient4015"
+       xlink:href="#linearGradient5048-4"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient5048-4">
+      <stop
+         id="stop5050-2"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="0" />
+      <stop
+         id="stop5056-1"
+         style="stop-color:#000000;stop-opacity:1"
+         offset="0.5" />
+      <stop
+         id="stop5052-1"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       inkscape:collect="always"
+       xlink:href="#linearGradient5060-6"
+       id="radialGradient3156"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(-0.03128083,0,0,0.02053005,31.850121,1036.6837)"
+       cx="605.71429"
+       cy="486.64789"
+       fx="605.71429"
+       fy="486.64789"
+       r="117.14286" />
+    <linearGradient
+       id="linearGradient5060-6">
+      <stop
+         id="stop5062-6"
+         style="stop-color:#000000;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop5064-9"
+         style="stop-color:#000000;stop-opacity:0"
+         offset="1" />
+    </linearGradient>
+    <radialGradient
+       r="117.14286"
+       fy="486.64789"
+       fx="605.71429"
+       cy="486.64789"
+       cx="605.71429"
+       gradientTransform="matrix(0.03128083,0,0,0.02053005,64.045118,1036.6837)"
+       gradientUnits="userSpaceOnUse"
+       id="radialGradient3061"
+       xlink:href="#linearGradient5060-6"
+       inkscape:collect="always" />
+    <linearGradient
+       id="linearGradient3846-5">
+      <stop
+         id="stop3848-48"
+         style="stop-color:#fff3cb;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3850-1"
+         style="stop-color:#fdde76;stop-opacity:1"
+         offset="0.26238" />
+      <stop
+         id="stop3852-28"
+         style="stop-color:#f9c440;stop-opacity:1"
+         offset="0.66093999" />
+      <stop
+         id="stop3854-9"
+         style="stop-color:#e48b20;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3856-6">
+      <stop
+         id="stop3858-8"
+         style="stop-color:#b67926;stop-opacity:1"
+         offset="0" />
+      <stop
+         id="stop3860-0"
+         style="stop-color:#eab41a;stop-opacity:1"
+         offset="1" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="3.9995727"
+     inkscape:cx="14.644105"
+     inkscape:cy="65.684016"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:grid-bbox="true"
+     inkscape:document-units="px"
+     inkscape:window-width="1703"
+     inkscape:window-height="933"
+     inkscape:window-x="41"
+     inkscape:window-y="121"
+     inkscape:window-maximized="0"
+     showguides="true"
+     inkscape:guide-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid3820"
+       empspacing="5"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata4117">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="layer1"
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     transform="translate(0,48)">
+    <g
+       id="g4089"
+       transform="matrix(1.0040259,0,0,1.0028296,-0.14065179,-1007.1659)">
+      <rect
+         width="69.89856"
+         height="4.9858918"
+         x="12.998364"
+         y="1044.2112"
+         id="rect2879"
+         style="opacity:0.3;fill:url(#linearGradient4015);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible" />
+      <path
+         d="m 12.998348,1044.2116 c 0,0 0,4.9853 0,4.9853 -1.610891,0.013 -3.894348,-1.1179 -3.894348,-2.4937 0,-1.3758 1.797632,-2.4916 3.894348,-2.4916 z"
+         id="path2881"
+         style="opacity:0.3;fill:url(#radialGradient3156);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+         inkscape:connector-curvature="0" />
+      <path
+         d="m 82.896898,1044.2116 c 0,0 0,4.9853 0,4.9853 1.610888,0.013 3.894344,-1.1179 3.894344,-2.4937 0,-1.3758 -1.797625,-2.4916 -3.894344,-2.4916 z"
+         id="path2883"
+         style="opacity:0.3;fill:url(#radialGradient3061);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       inkscape:connector-curvature="0"
+       style="color:#000000;fill:url(#radialGradient3144-4);fill-opacity:1.0;fill-rule:nonzero;stroke:url(#linearGradient3146-3);stroke-width:0.99992186000000005;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
+       id="path4160"
+       d="m 12.499959,-46.500076 c 16.269723,0 70.999996,0.0057 70.999996,0.0057 l 8.6e-5,88.994415 c 0,0 -47.333387,0 -71.000082,0 0,-29.666694 0,-59.333388 0,-89.00008 z"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="opacity:0.5;fill:none;stroke:url(#linearGradient3988);stroke-width:0.99999994;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
+       d="m 82.500002,41.499999 -69.000003,0 0,-87 69.000003,0 z"
+       id="rect6741-1"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="ccccc" />
+    <path
+       style="fill:#ffffff;fill-opacity:1;stroke:none"
+       d="m 15.999999,-43 43.946667,0 20.053333,19.974359 0,62.025641 -64,0 z"
+       id="path3102"
+       inkscape:connector-curvature="0"
+       sodipodi:nodetypes="cccccc" />
+    <path
+       inkscape:connector-curvature="0"
+       d="m 15.499999,-43.5 44.6875,0 20.312499,20.243902 0,62.756098 -64.999999,0 z"
+       style="opacity:0.2;fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.99999994px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       id="path3872" />
+    <g
+       id="g3949">
+      <path
+         sodipodi:nodetypes="cccc"
+         inkscape:connector-curvature="0"
+         id="path4025"
+         d="M 27.5,20.5 39.8,-21.499999 68.5,20.5 z"
+         style="fill:#f3ba00;fill-opacity:0.42682932;stroke:#f3ba00;stroke-width:3;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         style="fill:#ffffff;fill-opacity:1;stroke:#f3ba00;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 68,18 5,0 0,5 -5,0 z"
+         id="path3912"
+         inkscape:connector-curvature="0" />
+      <path
+         inkscape:connector-curvature="0"
+         id="path3945"
+         d="m 23,18 5,0 0,5 -5,0 z"
+         style="fill:#ffffff;fill-opacity:1;stroke:#f3ba00;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+      <path
+         style="fill:#ffffff;fill-opacity:1;stroke:#f3ba00;stroke-width:1.99999988;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+         d="m 37,-27 5,0 0,5 -5,0 z"
+         id="path3947"
+         inkscape:connector-curvature="0" />
+    </g>
+    <path
+       inkscape:connector-curvature="0"
+       style="opacity:0.2;fill:url(#linearGradient3051);fill-opacity:1;fill-rule:evenodd;stroke:none"
+       id="path3879"
+       d="m 13.999999,-45.999999 0,50.686364 c 0.0041,0.375118 0.09148,0.729854 0.240912,0.978098 0.149436,0.248244 0.347272,0.367298 0.54548,0.328248 l 66.612246,-19.856516 c 0.342654,-0.10174 0.59657,-0.653334 0.601362,-1.30635 l 0,-30.829844 z"
+       sodipodi:nodetypes="ccsccccc" />
+  </g>
+</svg>

File diff suppressed because it is too large
+ 1 - 0
img/mime/96/odp.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/ods.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/odt.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/pdf.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/ppt.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/txt.svg


File diff suppressed because it is too large
+ 1 - 0
img/mime/96/xls.svg


BIN
img/mime/base.png


BIN
img/mime/table.png