Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/apps.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Hülsmann <fh@cbix.de>2012-04-19 03:46:45 +0400
committerFlorian Hülsmann <fh@cbix.de>2012-04-19 03:46:45 +0400
commit5c39f659c656e285791ebde64d9ec8120f45406e (patch)
treecb1dbd968f4410872a8bd2356a073299a69db425 /files_svgedit
parent824a57042b31277570a3dd6e713ea3aa9143ea70 (diff)
updated from sourceforge repo
Diffstat (limited to 'files_svgedit')
-rw-r--r--files_svgedit/README20
-rw-r--r--files_svgedit/RELEASE24
-rw-r--r--files_svgedit/ROADMAP13
-rw-r--r--files_svgedit/ajax/save.php12
-rw-r--r--files_svgedit/appinfo/info.xml4
-rw-r--r--files_svgedit/css/ocsvg.css30
-rw-r--r--files_svgedit/index.php6
-rw-r--r--files_svgedit/js/base64.js143
-rw-r--r--files_svgedit/js/jsPDF/MIT-LICENSE.txt20
-rw-r--r--files_svgedit/js/jsPDF/README3
-rw-r--r--files_svgedit/js/jsPDF/jspdf.js756
-rwxr-xr-xfiles_svgedit/js/jsPDF/jspdf.min.js57
-rw-r--r--files_svgedit/js/ocsvg.js20
-rw-r--r--files_svgedit/js/ocsvgEditor.js263
-rw-r--r--files_svgedit/js/svgToPdf.js251
-rw-r--r--files_svgedit/templates/editor.php49
16 files changed, 1558 insertions, 113 deletions
diff --git a/files_svgedit/README b/files_svgedit/README
index 70dc324f4..c1a8c4353 100644
--- a/files_svgedit/README
+++ b/files_svgedit/README
@@ -5,8 +5,9 @@ Copyright by Florian Hülsmann, 2012
http://ocsvg.cbix.de
License:
- LGPLv3 (plugin, php and javascript code)
+ LGPLv3 (plugin, php and javascript code; if not otherwise mentioned in the specific file)
MIT License/Apache License (svg-edit, http://code.google.com/p/svg-edit)
+ MIT License (jsPDF, https://github.com/willowsystems/jsPDF, originally https://github.com/MrRio/jsPDF)
Creative Commons 3.0 by-sa (artwork, css stylesheets)
Authors:
@@ -14,21 +15,26 @@ Authors:
Description:
This app enables you to view, create and modify SVG files inside
- the ownCloud user interface.
+ the ownCloud user interface. It's also great as a tool for creating
+ PDF files and PNG graphics.
Installation:
Copy this folder to your ownCloud's /apps/ directory, rename it to
- "files_svgedit" and enable the app in the admin interface.
+ "files_svgedit" and enable the app in the admin interface. Or use
+ the official ownCloud app repo (appstore) for the latest stable version.
Usage:
To edit an SVG file, simply click on it in your directory listing.
+ Saving, exporting and downloading can be done when clicking "Save"
+ in the editor.
Updating svg-edit:
- To get the latest trunk version of svg-edit, go to files_svgedit/svg-edit
+ To get the latest trunk version of svg-edit, go to files_svgedit/
and execute the following commands:
-
- svn up
- cp embedapi.js ../js/svg-edit/
+
+ rm -rf svg-edit
+ svn export http://svg-edit.googlecode.com/svn/trunk/editor svg-edit
+ cp svg-edit/embedapi.js js/svg-edit/
But you should first check if there've been changes to the svg-edit
project that could make it incompatible to ocsvg!
diff --git a/files_svgedit/RELEASE b/files_svgedit/RELEASE
index 1d4eaa125..8c74b6a3d 100644
--- a/files_svgedit/RELEASE
+++ b/files_svgedit/RELEASE
@@ -3,13 +3,31 @@ Copyright (c) 2012 Florian Hülsmann <fh@cbix.de>
Here you find change log and release notes!
+2012/04/19 - beta5/0.2
+ * using a better maintained fork of jsPDF by willowsystems
+ * changing possibly irritating error messages on saving
+ * bug fixes:
+ * font size correctly set on PDF export
+ * always asking to overwrite existing file
+
+2012/04/16 - beta4/0.2
+ * bug fixes:
+ * use native confirm dialog if OCdialogs is not available
+ * fixed asynchronous svg saving
+
+2012/04/15 - beta3/0.2
+ * PDF export (using jsPDF)
+ * PNG export working better (because of the canvas preview)
+ * complete new saving dialog, integrates export
+ * create new image from file manager
+ * bug fixes:
+ * no saving error if mtime=0
+ * close button working
+
2012/04/04 - beta2/0.2
* PNG export (depending on browser's canvas capabilities)
* got rid of quit confirmation dialog when nothing has changed
* major bug fixes
-
- known issues:
- * PNG export not working reliable
2012/03/30 - beta1/0.2
Changing everything by using svgedit 2.6 (trunk version)
diff --git a/files_svgedit/ROADMAP b/files_svgedit/ROADMAP
index d6072abe6..9f2ed29e6 100644
--- a/files_svgedit/ROADMAP
+++ b/files_svgedit/ROADMAP
@@ -1,13 +1,16 @@
-Roadmap for ocsvg (SVG editor for ownCloud) as of 0.2-beta2
+Planned features for ocsvg (SVG editor for ownCloud) as of 0.2-beta5
beta:
- * l10n (set language to the current owncloud language)
- * better usage of jQuery UI and OCdialogs (export options etc.)
- * integration in "New File" drop down in file manager, create new svg file
+ * more saving options (PDF meta information, ...)
+ * multiple PDF pages (e.g. split by layer, render single pages)
+ * include images into exported PDF (if possible with jsPDF)
+ * printing button (like the files_pdfview app)
+ * better integration of svg-edit features (doc properties etc.)
1.0:
* file picker dialogs for image/svg import and saving
+ * l10n (set svg-edit language to the current owncloud language)
Ideas for the future:
* collaborative editing
- * PDF export (possible?)
+ * PDF export of more element types (paths, gradients, arrows etc. if possible)
diff --git a/files_svgedit/ajax/save.php b/files_svgedit/ajax/save.php
index 36e4e24a8..0a0f19e52 100644
--- a/files_svgedit/ajax/save.php
+++ b/files_svgedit/ajax/save.php
@@ -28,10 +28,14 @@ if($path != '' && $mtime != '') {
if(OC_Filesystem::file_exists($path)) {
// Get file mtime
$filemtime = OC_Filesystem::filemtime($path);
- if(!$force && $mtime != $filemtime) {
- // Then the file has changed since opening
- OC_JSON::error(array("data" => array("message" => "File has been modified since opening!")));
- OC_Log::write('files_svgedit',"File: ".$path." modified since opening.",OC_Log::ERROR);
+ if(!$force && $mtime != $filemtime) {
+ if($mtime == 0) {
+ $msg = "File already exists!";
+ } else {
+ $msg = "File has been modified since opening!";
+ }
+ OC_JSON::error(array("data" => array("message" => $msg)));
+ //OC_Log::write('files_svgedit',"File: ".$path." modified since opening.",OC_Log::ERROR);
exit();
}
} else {
diff --git a/files_svgedit/appinfo/info.xml b/files_svgedit/appinfo/info.xml
index 1bf5574f1..f48148f33 100644
--- a/files_svgedit/appinfo/info.xml
+++ b/files_svgedit/appinfo/info.xml
@@ -2,8 +2,8 @@
<info>
<id>files_svgedit</id>
<name>SVG Editor</name>
- <description>A complete javascript interface to view, modify and create vector graphics and export them to PNG file directly in ownCloud. Based on svg-edit 2.6 (http://svg-edit.googlecode.com).</description>
- <version>0.2-beta2</version>
+ <description>Create and modify vector graphics, export them to PNG (canvg-powered) or PDF (with help of jsPDF, only basic shapes and text). Based on svg-edit 2.6 (http://svg-edit.googlecode.com).</description>
+ <version>0.2-beta5</version>
<licence>LGPLv3</licence>
<author>Florian Hülsmann</author>
<require>2</require>
diff --git a/files_svgedit/css/ocsvg.css b/files_svgedit/css/ocsvg.css
index 0509b449f..f48888683 100644
--- a/files_svgedit/css/ocsvg.css
+++ b/files_svgedit/css/ocsvg.css
@@ -1,3 +1,10 @@
+#navigation > ul > li:first-child {
+ background: url("../../../core/img/breadcrumb-start.svg") no-repeat scroll 12.5em 0 transparent;
+ padding-right: 1em;
+ position: fixed;
+ width: 12.5em;
+}
+
div#svgEditor{
position: fixed;
display: block;
@@ -10,3 +17,26 @@ iframe#svgedit {
width: 100%;
height: 100%;
}
+
+div#controls {
+ padding-left: 1em;
+}
+
+div#content {
+ background-color: #888888;
+}
+
+div#canvasPreview, div#svgtopdfPreview {
+ width: 100%;
+ max-height: 250px;
+ overflow: auto;
+}
+
+div#svgtopdfPreview {
+ background-color: #FFFFFF;
+}
+
+div#svgEditorSave {
+ width: 400px;
+ height: 300px;
+}
diff --git a/files_svgedit/index.php b/files_svgedit/index.php
index 2d70d568a..0d0b455da 100644
--- a/files_svgedit/index.php
+++ b/files_svgedit/index.php
@@ -10,6 +10,11 @@ OC_Util::addScript('files_svgedit', 'svg-edit/embedapi');
OC_Util::addScript('files_svgedit', 'ocsvgEditor');
OC_Util::addScript('files_svgedit', 'canvg/canvg');
OC_Util::addScript('files_svgedit', 'canvg/rgbcolor');
+OC_Util::addScript('files_svgedit', 'base64');
+//OC_Util::addScript('files_svgedit', 'jsPDF/libs/sprintf');
+//OC_Util::addScript('files_svgedit', 'jsPDF/jspdf');
+OC_Util::addScript('files_svgedit', 'jsPDF/jspdf.min');
+OC_Util::addScript('files_svgedit', 'svgToPdf');
OC_App::setActiveNavigationEntry('files_index');
$path = $_GET['file'];
if(method_exists('OC_Filesystem', 'is_writable')) {
@@ -23,7 +28,6 @@ if(isset($_GET['file']) and $writable) {
} else {
$filecontents = "";
$filemtime = 0;
- $path = "";
}
$tmpl = new OC_TEMPLATE( "files_svgedit", "editor", "user" );
diff --git a/files_svgedit/js/base64.js b/files_svgedit/js/base64.js
new file mode 100644
index 000000000..7d9536a4f
--- /dev/null
+++ b/files_svgedit/js/base64.js
@@ -0,0 +1,143 @@
+
+/**
+*
+* Base64 encode / decode
+* http://www.webtoolkit.info/
+*
+**/
+
+var Base64 = {
+
+ // private property
+ _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
+
+ // public method for encoding
+ encode : function (input) {
+ var output = "";
+ var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = Base64._utf8_encode(input);
+
+ while (i < input.length) {
+
+ chr1 = input.charCodeAt(i++);
+ chr2 = input.charCodeAt(i++);
+ chr3 = input.charCodeAt(i++);
+
+ enc1 = chr1 >> 2;
+ enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
+ enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
+ enc4 = chr3 & 63;
+
+ if (isNaN(chr2)) {
+ enc3 = enc4 = 64;
+ } else if (isNaN(chr3)) {
+ enc4 = 64;
+ }
+
+ output = output +
+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
+
+ }
+
+ return output;
+ },
+
+ // public method for decoding
+ decode : function (input) {
+ var output = "";
+ var chr1, chr2, chr3;
+ var enc1, enc2, enc3, enc4;
+ var i = 0;
+
+ input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
+
+ while (i < input.length) {
+
+ enc1 = this._keyStr.indexOf(input.charAt(i++));
+ enc2 = this._keyStr.indexOf(input.charAt(i++));
+ enc3 = this._keyStr.indexOf(input.charAt(i++));
+ enc4 = this._keyStr.indexOf(input.charAt(i++));
+
+ chr1 = (enc1 << 2) | (enc2 >> 4);
+ chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
+ chr3 = ((enc3 & 3) << 6) | enc4;
+
+ output = output + String.fromCharCode(chr1);
+
+ if (enc3 != 64) {
+ output = output + String.fromCharCode(chr2);
+ }
+ if (enc4 != 64) {
+ output = output + String.fromCharCode(chr3);
+ }
+
+ }
+
+ output = Base64._utf8_decode(output);
+
+ return output;
+
+ },
+
+ // private method for UTF-8 encoding
+ _utf8_encode : function (string) {
+ string = string.replace(/\r\n/g,"\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++) {
+
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+
+ }
+
+ return utftext;
+ },
+
+ // private method for UTF-8 decoding
+ _utf8_decode : function (utftext) {
+ var string = "";
+ var i = 0;
+ var c = c1 = c2 = 0;
+
+ while ( i < utftext.length ) {
+
+ c = utftext.charCodeAt(i);
+
+ if (c < 128) {
+ string += String.fromCharCode(c);
+ i++;
+ }
+ else if((c > 191) && (c < 224)) {
+ c2 = utftext.charCodeAt(i+1);
+ string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
+ i += 2;
+ }
+ else {
+ c2 = utftext.charCodeAt(i+1);
+ c3 = utftext.charCodeAt(i+2);
+ string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
+ i += 3;
+ }
+
+ }
+
+ return string;
+ }
+
+}
diff --git a/files_svgedit/js/jsPDF/MIT-LICENSE.txt b/files_svgedit/js/jsPDF/MIT-LICENSE.txt
new file mode 100644
index 000000000..4a7d43d9d
--- /dev/null
+++ b/files_svgedit/js/jsPDF/MIT-LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2010 James Hall, https://github.com/MrRio/jsPDF
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/files_svgedit/js/jsPDF/README b/files_svgedit/js/jsPDF/README
new file mode 100644
index 000000000..b47dd3606
--- /dev/null
+++ b/files_svgedit/js/jsPDF/README
@@ -0,0 +1,3 @@
+jsPDF is a library to generate PDF files using Javascript. It can work both client side or server side. See the examples folder.
+
+You must run the Downloadify example using a webserver due to Flash restrictions. \ No newline at end of file
diff --git a/files_svgedit/js/jsPDF/jspdf.js b/files_svgedit/js/jsPDF/jspdf.js
new file mode 100644
index 000000000..1b152c66e
--- /dev/null
+++ b/files_svgedit/js/jsPDF/jspdf.js
@@ -0,0 +1,756 @@
+/** @preserve
+ * ====================================================================
+ * jsPDF
+ * Copyright (c) 2010 James Hall, https://github.com/MrRio/jsPDF
+ * Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ====================================================================
+ */
+
+/**
+ * Creates new jsPDF document object instance
+ * @constructor jsPDF
+ * @param orientation One of "portrait" or "landscape" (or shortcuts "p" (Default), "l")
+ * @param unit Measurement unit to be used when coordinates are specified. One of "pt" (points), "mm" (Default), "cm", "in"
+ * @param format One of 'a3', 'a4' (Default),'a5' ,'letter' ,'legal'
+ * @returns {jsPDF}
+ */
+var jsPDF = function(/** String */ orientation, /** String */ unit, /** String */ format){
+
+ // Default parameter values
+ if (typeof orientation === 'undefined') orientation = 'p'
+ else orientation = orientation.toString().toLowerCase()
+ if (typeof unit === 'undefined') unit = 'mm'
+ if (typeof format === 'undefined') format = 'a4'
+
+ var format_as_string = format.toString().toLowerCase()
+ , HELVETICA = "helvetica"
+ , TIMES = "times"
+ , COURIER = "courier"
+ , NORMAL = "normal"
+ , BOLD = "bold"
+ , ITALIC = "italic"
+ , BOLD_ITALIC = "bolditalic"
+
+ , version = '20120220'
+ , content = []
+ , content_length = 0
+
+ , pdfVersion = '1.3' // PDF Version
+ , pageFormats = { // Size in pt of various paper formats
+ 'a3': [841.89, 1190.55]
+ , 'a4': [595.28, 841.89]
+ , 'a5': [420.94, 595.28]
+ , 'letter': [612, 792]
+ , 'legal': [612, 1008]
+ }
+ , textColor = '0 g'
+ , drawColor = '0 G'
+ , page = 0
+ , objectNumber = 2 // 'n' Current object number
+ , outToPages = false // switches where out() prints. outToPages true = push to pages obj. outToPages false = doc builder content
+ , pages = []
+ , offsets = [] // List of offsets. Activated and reset by buildDocument(). Pupulated by various calls buildDocument makes.
+ , fonts = [] // List of fonts
+ , fontmap = {} // mapping structure - performance layer. See addFont()
+ , fontName = HELVETICA // Default font
+ , fontType = NORMAL // Default type
+ , activeFontKey // will be string representing the KEY of the font as combination of fontName + fontType
+ , lineWidth = 0.200025 // 2mm
+ , pageHeight
+ , pageWidth
+ , k // Scale factor
+ , documentProperties = {}
+ , fontSize = 16 // Default font size
+ , textColor = "0 g"
+ , lineCapID = 0
+ , lineJoinID = 0
+
+ /////////////////////
+ // Private functions
+ /////////////////////
+ // simplified (speedier) replacement for sprintf's %.2f conversion
+ , f2 = function(number){
+ return number.toFixed(2)
+ }
+ // simplified (speedier) replacement for sprintf's %.3f conversion
+ , f3 = function(number){
+ return number.toFixed(3)
+ }
+ // simplified (speedier) replacement for sprintf's %02d
+ , padd2 = function(number) {
+ var n = (number).toFixed(0)
+ if ( number < 10 ) return '0' + n
+ else return n
+ }
+ // simplified (speedier) replacement for sprintf's %02d
+ , padd10 = function(number) {
+ var n = (number).toFixed(0)
+ if (n.length < 10) return new Array( 11 - n.length ).join( '0' ) + n
+ else return n
+ }
+ , out = function(string) {
+ if(outToPages /* set by beginPage */) {
+ pages[page].push(string)
+ } else {
+ content.push(string)
+ content_length += string.length + 1 // +1 is for '\n' that will be used to join contents of content
+ }
+ }
+ , newObject = function() {
+ // Begin a new object
+ objectNumber ++
+ offsets[objectNumber] = content_length
+ out(objectNumber + ' 0 obj');
+ }
+ , putPages = function() {
+ var wPt = pageWidth * k
+ var hPt = pageHeight * k
+
+ // outToPages = false as set in endDocument(). out() writes to content.
+
+ for(n=1; n <= page; n++) {
+ newObject()
+ out('<</Type /Page')
+ out('/Parent 1 0 R');
+ out('/Resources 2 0 R')
+ out('/Contents ' + (objectNumber + 1) + ' 0 R>>')
+ out('endobj')
+
+ // Page content
+ p = pages[n].join('\n')
+ newObject()
+ out('<</Length ' + p.length + '>>')
+ putStream(p)
+ out('endobj')
+ }
+ offsets[1] = content_length
+ out('1 0 obj')
+ out('<</Type /Pages')
+ var kids = '/Kids ['
+ for (i = 0; i < page; i++) {
+ kids += (3 + 2 * i) + ' 0 R '
+ }
+ out(kids + ']')
+ out('/Count ' + page)
+ out('/MediaBox [0 0 '+f2(wPt)+' '+f2(hPt)+']')
+ out('>>')
+ out('endobj');
+ }
+ , putStream = function(str) {
+ out('stream')
+ out(str)
+ out('endstream')
+ }
+ , putResources = function() {
+ putFonts()
+ // Resource dictionary
+ offsets[2] = content_length
+ out('2 0 obj')
+ out('<<')
+ putResourceDictionary()
+ out('>>')
+ out('endobj')
+ }
+ , putFonts = function() {
+ for (var i = 0, l=fonts.length; i < l; i++) {
+ putFont(fonts[i])
+ }
+ }
+ , putFont = function(font) {
+ newObject()
+ font.number = objectNumber
+ out('<</BaseFont/' + font.name + '/Type/Font')
+ out('/Subtype/Type1>>')
+ out('endobj')
+ }
+ , addFont = function(name, fontName, fontType, undef) {
+ var fontkey = 'F' + (fonts.length + 1).toString(10)
+
+ fonts.push({'key': fontkey, 'number': objectNumber, 'name': name, 'fontName': fontName, 'type': fontType})
+ // this is mapping structure for quick font lookup.
+ // returns the KEY of the font within fonts array.
+ if (fontmap[fontName] === undef){
+ fontmap[fontName] = {} // fontType is a var interpreted and converted to appropriate string. don't wrap in quotes.
+ }
+ fontmap[fontName][fontType] = fontkey
+ }
+ , addFonts = function() {
+ addFont('Helvetica', HELVETICA, NORMAL)
+ addFont('Helvetica-Bold', HELVETICA, BOLD)
+ addFont('Helvetica-Oblique', HELVETICA, ITALIC)
+ addFont('Helvetica-BoldOblique', HELVETICA, BOLD_ITALIC)
+ addFont('Courier', COURIER, NORMAL)
+ addFont('Courier-Bold', COURIER, BOLD)
+ addFont('Courier-Oblique', COURIER, ITALIC)
+ addFont('Courier-BoldOblique', COURIER, BOLD_ITALIC)
+ addFont('Times-Roman', TIMES, NORMAL)
+ addFont('Times-Bold', TIMES, BOLD)
+ addFont('Times-Italic', TIMES, ITALIC)
+ addFont('Times-BoldItalic', TIMES, BOLD_ITALIC)
+ }
+ , putResourceDictionary = function() {
+ out('/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]')
+ out('/Font <<')
+ // Do this for each font, the '1' bit is the index of the font
+ for (var i = 0; i < fonts.length; i++) {
+ out('/' + fonts[i].key + ' ' + fonts[i].number + ' 0 R')
+ }
+
+ out('>>')
+ out('/XObject <<')
+ putXobjectDict()
+ out('>>')
+ }
+ , putXobjectDict = function() {
+ // @TODO: Loop through images, or other data objects
+ }
+ , putInfo = function() {
+ out('/Producer (jsPDF ' + version + ')')
+ if(documentProperties.title != undefined) {
+ out('/Title (' + pdfEscape(documentProperties.title) + ')')
+ }
+ if(documentProperties.subject != undefined) {
+ out('/Subject (' + pdfEscape(documentProperties.subject) + ')')
+ }
+ if(documentProperties.author != undefined) {
+ out('/Author (' + pdfEscape(documentProperties.author) + ')')
+ }
+ if(documentProperties.keywords != undefined) {
+ out('/Keywords (' + pdfEscape(documentProperties.keywords) + ')')
+ }
+ if(documentProperties.creator != undefined) {
+ out('/Creator (' + pdfEscape(documentProperties.creator) + ')')
+ }
+ var created = new Date()
+ out('/CreationDate (D:' +
+ [
+ created.getFullYear()
+ , padd2(created.getMonth() + 1)
+ , padd2(created.getDate())
+ , padd2(created.getHours())
+ , padd2(created.getMinutes())
+ , padd2(created.getSeconds())
+ ].join('')+
+ ')'
+ )
+ }
+ , putCatalog = function () {
+ out('/Type /Catalog')
+ out('/Pages 1 0 R')
+ // @TODO: Add zoom and layout modes
+ out('/OpenAction [3 0 R /FitH null]')
+ out('/PageLayout /OneColumn')
+ }
+ , putTrailer = function () {
+ out('/Size ' + (objectNumber + 1))
+ out('/Root ' + objectNumber + ' 0 R')
+ out('/Info ' + (objectNumber - 1) + ' 0 R')
+ }
+ , beginPage = function() {
+ page ++
+ // Do dimension stuff
+ outToPages = true
+ pages[page] = []
+ }
+ , _addPage = function() {
+ beginPage()
+ // Set line width
+ out(f2(lineWidth * k) + ' w')
+ // Set draw color
+ out(drawColor)
+ // resurrecting non-default line caps, joins
+ if (lineCapID !== 0) out(lineCapID.toString(10)+' J')
+ if (lineJoinID !== 0) out(lineJoinID.toString(10)+' j')
+ }
+ , getFont = function(fontName, fontType, undef) {
+ var key
+ try {
+ key = fontmap[fontName][fontType] // returns a string like 'F3' - the KEY corresponding tot he font + type combination.
+ } catch (e) {
+ key = undef
+ }
+ if (!key){
+ throw new Error("Unable to look up font label for font '"+fontName+"', '"+fontType+"'. Refer to getFontList() for available fonts.")
+ }
+ return key
+ }
+ , buildDocument = function() {
+
+ outToPages = false // switches out() to content
+ content = []
+ offsets = []
+
+ // putHeader()
+ out('%PDF-' + pdfVersion)
+
+ putPages()
+
+ putResources()
+
+ // Info
+ newObject()
+ out('<<')
+ putInfo()
+ out('>>')
+ out('endobj')
+
+ // Catalog
+ newObject()
+ out('<<')
+ putCatalog()
+ out('>>')
+ out('endobj')
+
+ // Cross-ref
+ var o = content_length
+ out('xref')
+ out('0 ' + (objectNumber + 1))
+ out('0000000000 65535 f ')
+ for (var i=1; i <= objectNumber; i++) {
+ out(padd10(offsets[i]) + ' 00000 n ')
+ }
+ // Trailer
+ out('trailer')
+ out('<<')
+ putTrailer()
+ out('>>')
+ out('startxref')
+ out(o)
+ out('%%EOF')
+
+ outToPages = true
+
+ return content.join('\n')
+ }
+ , pdfEscape = function(text) {
+ return text.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)')
+ }
+
+ // Public API
+ , _jsPDF = {
+ /**
+ * Adds (and transfers the focus to) new page to the PDF document.
+ * @function
+ * @returns {jsPDF}
+ * @name jsPDF.addPage
+ */
+ addPage: function() {
+ _addPage()
+ return _jsPDF
+ },
+ /**
+ * Adds text to page. Supports adding multiline text when 'text' argument is an Array of Strings.
+ * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
+ * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
+ * @param {String|Array} text String or array of strings to be added to the page. Each line is shifted one line down per font, spacing settings declared before this call.
+ * @function
+ * @returns {jsPDF}
+ * @name jsPDF.text
+ */
+ text: function(x, y, text) {
+ /**
+ * Inserts something like this into PDF
+ BT
+ /F1 16 Tf % Font name + size
+ 16 TL % How many units down for next line in multiline text
+ 0 g % color
+ 28.35 813.54 Td % position
+ (line one) Tj
+ T* (line two) Tj
+ T* (line three) Tj
+ ET
+ */
+
+ var newtext, str
+
+ if (typeof text === 'string'){
+ str = pdfEscape(text)
+ } else /* Array */{
+ // we don't want to destroy original text array, so cloning it
+ newtext = text.concat()
+ // we do array.join('text that must not be PDFescaped")
+ // thus, pdfEscape eash component separately
+ for ( var i = newtext.length - 1; i !== -1 ; i--) {
+ newtext[i] = pdfEscape( newtext[i] )
+ }
+ str = newtext.join( ") Tj\nT* (" )
+ }
+ // Using "'" ("go next line and render text" mark) would save space but would complicate our rendering code, templates
+
+ // BT .. ET does NOT have default settings for Tf. You must state that explicitely every time for BT .. ET
+ // if you want text transformation matrix (+ multiline) to work reliably (which reads sizes of things from font declarations)
+ // Thus, there is NO useful, *reliable* concept of "default" font for a page.
+ // The fact that "default" (reuse font used before) font worked before in basic cases is an accident
+ // - readers dealing smartly with brokenness of jsPDF's markup.
+ out(
+ 'BT\n/' +
+ activeFontKey + ' ' + fontSize + ' Tf\n' + // font face, style, size
+ fontSize + ' TL\n' + // line spacing
+ textColor +
+ '\n' + f2(x * k) + ' ' + f2((pageHeight - y) * k) + ' Td\n(' +
+ str +
+ ') Tj\nET'
+ )
+ return _jsPDF
+ },
+ line: function(x1, y1, x2, y2) {
+ out(
+ f2(x1 * k) + ' ' + f2((pageHeight - y1) * k) + ' m ' +
+ f2(x2 * k) + ' ' + f2((pageHeight - y2) * k) + ' l S'
+ )
+ return _jsPDF
+ },
+ /**
+ * Adds series of curves (straight lines or cubic bezier curves) to canvas, starting at `x`, `y` coordinates.
+ * All data points in `lines` are relative to last line origin.
+ * `x`, `y` become x1,y1 for first line / curve in the set.
+ * For lines you only need to specify [x2, y2] - (ending point) vector against x1, y1 starting point.
+ * For bezier curves you need to specify [x2,y2,x3,y3,x4,y4] - vectors to control points 1, 2, ending point. All vectors are against the start of the curve - x1,y1.
+ *
+ * @example .lines(212,110,[[2,2],[-2,2],[1,1,2,2,3,3],[2,1]], 10) // line, line, bezier curve, line
+ * @param {Number} x Coordinate (in units declared at inception of PDF document) against left edge of the page
+ * @param {Number} y Coordinate (in units declared at inception of PDF document) against upper edge of the page
+ * @param {Array} lines Array of *vector* shifts as pairs (lines) or sextets (cubic bezier curves).
+ * @param {Number} scale (Defaults to [1.0,1.0]) x,y Scaling factor for all vectors. Elements can be any floating number Sub-one makes drawing smaller. Over-one grows the drawing. Negative flips the direction.
+ * @function
+ * @returns {jsPDF}
+ * @name jsPDF.text
+ */
+ lines: function(x, y, lines, scale) {
+ var undef
+ scale = scale === undef ? [1,1] : scale
+
+ // starting point
+ out(f3(x * k) + ' ' + f3((pageHeight - y) * k) + ' m ')
+
+ var scalex = scale[0]
+ , scaley = scale[1]
+ , i = 0
+ , l = lines.length
+ , leg
+ , x2, y2 // bezier only. In page default measurement "units", *after* scaling
+ , x3, y3 // bezier only. In page default measurement "units", *after* scaling
+ // ending point for all, lines and bezier. . In page default measurement "units", *after* scaling
+ , x4 = x // last / ending point = starting point for first item.
+ , y4 = y // last / ending point = starting point for first item.
+
+ for (; i < l; i++) {
+ leg = lines[i]
+ if (leg.length === 2){
+ // simple line
+ x4 = leg[0] * scalex + x4 // here last x4 was prior ending point
+ y4 = leg[1] * scaley + y4 // here last y4 was prior ending point
+ out(f3(x4 * k) + ' ' + f3((pageHeight - y4) * k) + ' l')
+ } else {
+ // bezier curve
+ x2 = leg[0] * scalex + x4 // here last x4 is prior ending point
+ y2 = leg[1] * scaley + y4 // here last y4 is prior ending point
+ x3 = leg[2] * scalex + x4 // here last x4 is prior ending point
+ y3 = leg[3] * scaley + y4 // here last y4 is prior ending point
+ x4 = leg[4] * scalex + x4 // here last x4 was prior ending point
+ y4 = leg[5] * scaley + y4 // here last y4 was prior ending point
+ out(
+ f3(x2 * k) + ' ' +
+ f3((pageHeight - y2) * k) + ' ' +
+ f3(x3 * k) + ' ' +
+ f3((pageHeight - y3) * k) + ' ' +
+ f3(x4 * k) + ' ' +
+ f3((pageHeight - y4) * k) + ' c'
+ )
+ }
+ }
+ // stroking the path
+ out('S')
+ return _jsPDF
+ },
+ rect: function(x, y, w, h, style) {
+ var op = 'S'
+ if (style === 'F') {
+ op = 'f'
+ } else if (style === 'FD' || style === 'DF') {
+ op = 'B'
+ }
+ out([
+ f2(x * k)
+ , f2((pageHeight - y) * k)
+ , f2(w * k)
+ , f2(-h * k)
+ , 're'
+ , op
+ ].join(' '))
+ return _jsPDF
+ },
+ ellipse: function(x, y, rx, ry, style) {
+ var op = 'S'
+ if (style === 'F') {
+ op = 'f'
+ } else if (style === 'FD' || style === 'DF') {
+ op = 'B'
+ }
+ var lx = 4/3*(Math.SQRT2-1)*rx
+ , ly = 4/3*(Math.SQRT2-1)*ry
+
+ out([
+ f2((x+rx)*k)
+ , f2((pageHeight-y)*k)
+ , 'm'
+ , f2((x+rx)*k)
+ , f2((pageHeight-(y-ly))*k)
+ , f2((x+lx)*k)
+ , f2((pageHeight-(y-ry))*k)
+ , f2(x*k)
+ , f2((pageHeight-(y-ry))*k)
+ , 'c'
+ ].join(' '))
+ out([
+ f2((x-lx)*k)
+ , f2((pageHeight-(y-ry))*k)
+ , f2((x-rx)*k)
+ , f2((pageHeight-(y-ly))*k)
+ , f2((x-rx)*k)
+ , f2((pageHeight-y)*k)
+ , 'c'
+ ].join(' '))
+ out([
+ f2((x-rx)*k)
+ , f2((pageHeight-(y+ly))*k)
+ , f2((x-lx)*k)
+ , f2((pageHeight-(y+ry))*k)
+ , f2(x*k)
+ , f2((pageHeight-(y+ry))*k)
+ , 'c'
+ ].join(' '))
+ out([
+ f2((x+lx)*k)
+ , f2((pageHeight-(y+ry))*k)
+ , f2((x+rx)*k)
+ , f2((pageHeight-(y+ly))*k)
+ , f2((x+rx)*k)
+ , f2((pageHeight-y)*k)
+ ,'c'
+ , op
+ ].join(' '))
+ return _jsPDF
+ },
+ circle: function(x, y, r, style) {
+ return this.ellipse(x, y, r, r, style)
+ },
+ setProperties: function(properties) {
+ documentProperties = properties
+ return _jsPDF
+ },
+ addImage: function(imageData, format, x, y, w, h) {
+ return _jsPDF
+ },
+ setFontSize: function(size) {
+ fontSize = size
+ return _jsPDF
+ },
+ setFont: function(name) {
+ var _name = name.toLowerCase()
+ activeFontKey = getFont(_name, fontType)
+ // if font is not found, the above line blows up and we never go further
+ fontName = _name
+ return _jsPDF
+ },
+ setFontType: function(type) {
+ var _type = type.toLowerCase()
+ activeFontKey = getFont(fontName, _type)
+ // if font is not found, the above line blows up and we never go further
+ fontType = _type
+ return _jsPDF
+ },
+ getFontList: function(){
+ // TODO: iterate over fonts array or return copy of fontmap instead in case more are ever added.
+ return {
+ HELVETICA:[NORMAL, BOLD, ITALIC, BOLD_ITALIC]
+ , TIMES:[NORMAL, BOLD, ITALIC, BOLD_ITALIC]
+ , COURIER:[NORMAL, BOLD, ITALIC, BOLD_ITALIC]
+ }
+ },
+ setLineWidth: function(width) {
+ out((width * k).toFixed(2) + ' w')
+ return _jsPDF
+ },
+ setDrawColor: function(r,g,b) {
+ var color
+ if ((r===0 && g===0 && b===0) || (typeof g === 'undefined')) {
+ color = f3(r/255) + ' G'
+ } else {
+ color = [f3(r/255), f3(g/255), f3(b/255), 'RG'].join(' ')
+ }
+ out(color)
+ return _jsPDF
+ },
+ setFillColor: function(r,g,b) {
+ var color
+ if ((r===0 && g===0 && b===0) || (typeof g === 'undefined')) {
+ color = f3(r/255) + ' g'
+ } else {
+ color = [f3(r/255), f3(g/255), f3(b/255), 'rg'].join(' ')
+ }
+ out(color)
+ return _jsPDF
+ },
+ setTextColor: function(r,g,b) {
+ if ((r===0 && g===0 && b===0) || (typeof g === 'undefined')) {
+ textColor = f3(r/255) + ' g'
+ } else {
+ textColor = [f3(r/255), f3(g/255), f3(b/255), 'rg'].join(' ')
+ }
+ return _jsPDF
+ },
+ CapJoinStyles: {
+ 0:0, 'butt':0, 'but':0, 'bevel':0
+ , 1:1, 'round': 1, 'rounded':1, 'circle':1
+ , 2:2, 'projecting':2, 'project':2, 'square':2, 'milter':2
+ },
+ setLineCap: function(style, undef) {
+ var id = this.CapJoinStyles[style]
+ if (id === undef) {
+ throw new Error("Line cap style of '"+style+"' is not recognized. See or extend .CapJoinStyles property for valid styles")
+ }
+ lineCapID = id
+ out(id.toString(10) + ' J')
+ },
+ setLineJoin: function(style, undef) {
+ var id = this.CapJoinStyles[style]
+ if (id === undef) {
+ throw new Error("Line join style of '"+style+"' is not recognized. See or extend .CapJoinStyles property for valid styles")
+ }
+ lineJoinID = id
+ out(id.toString(10) + ' j')
+ },
+ base64encode: function(data) {
+ // use native code if it's present
+ if (typeof btoa === 'function') return btoa(data)
+
+ /** @preserve
+ ====================================================================
+ base64 encoder
+ MIT, GPL
+
+ version: 1109.2015
+ discuss at: http://phpjs.org/functions/base64_encode
+ + original by: Tyler Akins (http://rumkin.com)
+ + improved by: Bayron Guevara
+ + improved by: Thunder.m
+ + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ + bugfixed by: Pellentesque Malesuada
+ + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ + improved by: Rafal Kukawski (http://kukawski.pl)
+ ====================================================================
+ */
+
+ var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
+ , b64a = b64.split('')
+ , o1, o2, o3, h1, h2, h3, h4, bits, i = 0,
+ ac = 0,
+ enc = "",
+ tmp_arr = [];
+
+ do { // pack three octets into four hexets
+ o1 = data.charCodeAt(i++);
+ o2 = data.charCodeAt(i++);
+ o3 = data.charCodeAt(i++);
+
+ bits = o1 << 16 | o2 << 8 | o3;
+
+ h1 = bits >> 18 & 0x3f;
+ h2 = bits >> 12 & 0x3f;
+ h3 = bits >> 6 & 0x3f;
+ h4 = bits & 0x3f;
+
+ // use hexets to index into b64, and append result to encoded string
+ tmp_arr[ac++] = b64a[h1] + b64a[h2] + b64a[h3] + b64a[h4];
+ } while (i < data.length);
+
+ enc = tmp_arr.join('');
+ var r = data.length % 3;
+ return (r ? enc.slice(0, r - 3) : enc) + '==='.slice(r || 3);
+
+ // end of base64 encoder MIT, GPL
+ },
+ output: function(type, options) {
+ var undef
+ switch (type){
+ case undef: return buildDocument()
+ case 'datauristring':
+ case 'datauristrlng':
+ return 'data:application/pdf;base64,' + this.base64encode(buildDocument())
+ case 'datauri':
+ case 'dataurl':
+ document.location.href = 'data:application/pdf;base64,' + this.base64encode(buildDocument()); break;
+ default: throw new Error('Output type "'+type+'" is not supported.')
+ }
+ // @TODO: Add different output options
+ }
+ }
+
+ /////////////////////////////////////////
+ // Initilisation if jsPDF Document object
+ /////////////////////////////////////////
+
+ if (unit == 'pt') {
+ k = 1
+ } else if(unit == 'mm') {
+ k = 72/25.4
+ } else if(unit == 'cm') {
+ k = 72/2.54
+ } else if(unit == 'in') {
+ k = 72
+ } else {
+ throw('Invalid unit: ' + unit)
+ }
+
+ // Dimensions are stored as user units and converted to points on output
+ if (format_as_string in pageFormats) {
+ pageHeight = pageFormats[format_as_string][1] / k
+ pageWidth = pageFormats[format_as_string][0] / k
+ } else {
+ try {
+ pageHeight = format[1]
+ pageWidth = format[0]
+ }
+ catch(err) {
+ throw('Invalid format: ' + format)
+ }
+ }
+
+ if (orientation === 'p' || orientation === 'portrait') {
+ orientation = 'p'
+ } else if (orientation === 'l' || orientation === 'landscape') {
+ orientation = 'l'
+ var tmp = pageWidth
+ pageWidth = pageHeight
+ pageHeight = tmp
+ } else {
+ throw('Invalid orientation: ' + orientation)
+ }
+
+ // Add the first page automatically
+ addFonts()
+ activeFontKey = getFont(fontName, fontType)
+ _addPage();
+
+ return _jsPDF
+} \ No newline at end of file
diff --git a/files_svgedit/js/jsPDF/jspdf.min.js b/files_svgedit/js/jsPDF/jspdf.min.js
new file mode 100755
index 000000000..e4ba15ebc
--- /dev/null
+++ b/files_svgedit/js/jsPDF/jspdf.min.js
@@ -0,0 +1,57 @@
+/*
+
+ ====================================================================
+ base64 encoder
+ MIT, GPL
+
+ version: 1109.2015
+ discuss at: http://phpjs.org/functions/base64_encode
+ + original by: Tyler Akins (http://rumkin.com)
+ + improved by: Bayron Guevara
+ + improved by: Thunder.m
+ + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ + bugfixed by: Pellentesque Malesuada
+ + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ + improved by: Rafal Kukawski (http://kukawski.pl)
+ ====================================================================
+
+ ====================================================================
+ jsPDF
+ Copyright (c) 2010 James Hall, https://github.com/MrRio/jsPDF
+ Copyright (c) 2012 Willow Systems Corporation, willow-systems.com
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ ====================================================================
+*/
+var jsPDF=function(k,s,x){k="undefined"===typeof k?"p":k.toString().toLowerCase();"undefined"===typeof s&&(s="mm");"undefined"===typeof x&&(x="a4");var H=x.toString().toLowerCase(),I=[],y=0,J={a3:[841.89,1190.55],a4:[595.28,841.89],a5:[420.94,595.28],letter:[612,792],legal:[612,1008]},K="0 g",z=0,m=2,E=!1,L=[],A=[],v=[],F={},M="helvetica",N="normal",G,h,B,c,o={},O=16,K="0 g",P=0,Q=0,e=function(a){return a.toFixed(2)},g=function(a){return a.toFixed(3)},C=function(a){var b=a.toFixed(0);return 10>a?
+"0"+b:b},b=function(a){E?L[z].push(a):(I.push(a),y+=a.length+1)},D=function(){m++;A[m]=y;b(m+" 0 obj")},j=function(a,b,d,c){var e="F"+(v.length+1).toString(10);v.push({key:e,number:m,name:a,fontName:b,type:d});F[b]===c&&(F[b]={});F[b][d]=e},T=function(){z++;E=!0;L[z]=[];b(e(0.200025*c)+" w");b("0 G");0!==P&&b(P.toString(10)+" J");0!==Q&&b(Q.toString(10)+" j")},R=function(a,b,d){var c;try{c=F[a][b]}catch(e){c=d}if(!c)throw Error("Unable to look up font label for font '"+a+"', '"+b+"'. Refer to getFontList() for available fonts.");
+return c},S=function(){E=!1;I=[];A=[];b("%PDF-1.3");var a=B*c,f=h*c;for(n=1;n<=z;n++){D();b("<</Type /Page");b("/Parent 1 0 R");b("/Resources 2 0 R");b("/Contents "+(m+1)+" 0 R>>");b("endobj");p=L[n].join("\n");D();b("<</Length "+p.length+">>");var d=p;b("stream");b(d);b("endstream");b("endobj")}A[1]=y;b("1 0 obj");b("<</Type /Pages");d="/Kids [";for(i=0;i<z;i++)d+=3+2*i+" 0 R ";b(d+"]");b("/Count "+z);b("/MediaBox [0 0 "+e(a)+" "+e(f)+"]");b(">>");b("endobj");a=0;for(f=v.length;a<f;a++)d=v[a],D(),
+d.number=m,b("<</BaseFont/"+d.name+"/Type/Font"),b("/Subtype/Type1>>"),b("endobj");A[2]=y;b("2 0 obj");b("<<");b("/ProcSet [/PDF /Text /ImageB /ImageC /ImageI]");b("/Font <<");for(a=0;a<v.length;a++)b("/"+v[a].key+" "+v[a].number+" 0 R");b(">>");b("/XObject <<");b(">>");b(">>");b("endobj");D();b("<<");b("/Producer (jsPDF 20120220)");void 0!=o.title&&b("/Title ("+w(o.title)+")");void 0!=o.subject&&b("/Subject ("+w(o.subject)+")");void 0!=o.author&&b("/Author ("+w(o.author)+")");void 0!=o.keywords&&
+b("/Keywords ("+w(o.keywords)+")");void 0!=o.creator&&b("/Creator ("+w(o.creator)+")");a=new Date;b("/CreationDate (D:"+[a.getFullYear(),C(a.getMonth()+1),C(a.getDate()),C(a.getHours()),C(a.getMinutes()),C(a.getSeconds())].join("")+")");b(">>");b("endobj");D();b("<<");b("/Type /Catalog");b("/Pages 1 0 R");b("/OpenAction [3 0 R /FitH null]");b("/PageLayout /OneColumn");b(">>");b("endobj");a=y;b("xref");b("0 "+(m+1));b("0000000000 65535 f ");for(f=1;f<=m;f++)d=A[f].toFixed(0),d=10>d.length?Array(11-
+d.length).join("0")+d:d,b(d+" 00000 n ");b("trailer");b("<<");b("/Size "+(m+1));b("/Root "+m+" 0 R");b("/Info "+(m-1)+" 0 R");b(">>");b("startxref");b(a);b("%%EOF");E=!0;return I.join("\n")},w=function(a){return a.replace(/\\/g,"\\\\").replace(/\(/g,"\\(").replace(/\)/g,"\\)")},l={addPage:function(){T();return l},text:function(a,f,d){if("string"===typeof d)d=w(d);else{for(var d=d.concat(),t=d.length-1;-1!==t;t--)d[t]=w(d[t]);d=d.join(") Tj\nT* (")}b("BT\n/"+G+" "+O+" Tf\n"+O+" TL\n"+K+"\n"+e(a*c)+
+" "+e((h-f)*c)+" Td\n("+d+") Tj\nET");return l},line:function(a,f,d,t){b(e(a*c)+" "+e((h-f)*c)+" m "+e(d*c)+" "+e((h-t)*c)+" l S");return l},lines:function(a,f,d,e){e=void 0===e?[1,1]:e;b(g(a*c)+" "+g((h-f)*c)+" m ");for(var q=e[0],e=e[1],r=0,k=d.length,j,m,o,s,u=f;r<k;r++)f=d[r],2===f.length?(a=f[0]*q+a,u=f[1]*e+u,b(g(a*c)+" "+g((h-u)*c)+" l")):(j=f[0]*q+a,m=f[1]*e+u,o=f[2]*q+a,s=f[3]*e+u,a=f[4]*q+a,u=f[5]*e+u,b(g(j*c)+" "+g((h-m)*c)+" "+g(o*c)+" "+g((h-s)*c)+" "+g(a*c)+" "+g((h-u)*c)+" c"));b("S");
+return l},rect:function(a,f,d,t,g){var r="S";if("F"===g)r="f";else if("FD"===g||"DF"===g)r="B";b([e(a*c),e((h-f)*c),e(d*c),e(-t*c),"re",r].join(" "));return l},ellipse:function(a,f,d,g,q){var r="S";if("F"===q)r="f";else if("FD"===q||"DF"===q)r="B";var q=4/3*(Math.SQRT2-1)*d,j=4/3*(Math.SQRT2-1)*g;b([e((a+d)*c),e((h-f)*c),"m",e((a+d)*c),e((h-(f-j))*c),e((a+q)*c),e((h-(f-g))*c),e(a*c),e((h-(f-g))*c),"c"].join(" "));b([e((a-q)*c),e((h-(f-g))*c),e((a-d)*c),e((h-(f-j))*c),e((a-d)*c),e((h-f)*c),"c"].join(" "));
+b([e((a-d)*c),e((h-(f+j))*c),e((a-q)*c),e((h-(f+g))*c),e(a*c),e((h-(f+g))*c),"c"].join(" "));b([e((a+q)*c),e((h-(f+g))*c),e((a+d)*c),e((h-(f+j))*c),e((a+d)*c),e((h-f)*c),"c",r].join(" "));return l},circle:function(a,b,d,c){return this.ellipse(a,b,d,d,c)},setProperties:function(a){o=a;return l},addImage:function(){return l},setFontSize:function(a){O=a;return l},setFont:function(a){a=a.toLowerCase();G=R(a,N);M=a;return l},setFontType:function(a){a=a.toLowerCase();G=R(M,a);N=a;return l},getFontList:function(){return{HELVETICA:["normal",
+"bold","italic","bolditalic"],TIMES:["normal","bold","italic","bolditalic"],COURIER:["normal","bold","italic","bolditalic"]}},setLineWidth:function(a){b((a*c).toFixed(2)+" w");return l},setDrawColor:function(a,c,d){a=0===a&&0===c&&0===d||"undefined"===typeof c?g(a/255)+" G":[g(a/255),g(c/255),g(d/255),"RG"].join(" ");b(a);return l},setFillColor:function(a,c,d){a=0===a&&0===c&&0===d||"undefined"===typeof c?g(a/255)+" g":[g(a/255),g(c/255),g(d/255),"rg"].join(" ");b(a);return l},setTextColor:function(a,
+b,c){K=0===a&&0===b&&0===c||"undefined"===typeof b?g(a/255)+" g":[g(a/255),g(b/255),g(c/255),"rg"].join(" ");return l},CapJoinStyles:{"0":0,butt:0,but:0,bevel:0,1:1,round:1,rounded:1,circle:1,2:2,projecting:2,project:2,square:2,milter:2},setLineCap:function(a,c){var d=this.CapJoinStyles[a];if(d===c)throw Error("Line cap style of '"+a+"' is not recognized. See or extend .CapJoinStyles property for valid styles");P=d;b(d.toString(10)+" J")},setLineJoin:function(a,c){var d=this.CapJoinStyles[a];if(d===
+c)throw Error("Line join style of '"+a+"' is not recognized. See or extend .CapJoinStyles property for valid styles");Q=d;b(d.toString(10)+" j")},base64encode:function(a){if("function"===typeof btoa)return btoa(a);var b="A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9,+,/,=".split(","),c,e,g,h,j=0,l=0,k="",k=[];do c=a.charCodeAt(j++),e=a.charCodeAt(j++),g=a.charCodeAt(j++),h=c<<16|e<<8|g,c=h>>18&63,e=h>>12&63,g=h>>6&63,h&=
+63,k[l++]=b[c]+b[e]+b[g]+b[h];while(j<a.length);k=k.join("");a=a.length%3;return(a?k.slice(0,a-3):k)+"===".slice(a||3)},output:function(a){switch(a){case void 0:return S();case "datauristring":case "datauristrlng":return"data:application/pdf;base64,"+this.base64encode(S());case "datauri":case "dataurl":document.location.href="data:application/pdf;base64,"+this.base64encode(S());break;default:throw Error('Output type "'+a+'" is not supported.');}}};if("pt"==s)c=1;else if("mm"==s)c=72/25.4;else if("cm"==
+s)c=72/2.54;else if("in"==s)c=72;else throw"Invalid unit: "+s;if(H in J)h=J[H][1]/c,B=J[H][0]/c;else try{h=x[1],B=x[0]}catch(U){throw"Invalid format: "+x;}if("p"===k||"portrait"===k)k="p";else if("l"===k||"landscape"===k)k="l",k=B,B=h,h=k;else throw"Invalid orientation: "+k;j("Helvetica","helvetica","normal");j("Helvetica-Bold","helvetica","bold");j("Helvetica-Oblique","helvetica","italic");j("Helvetica-BoldOblique","helvetica","bolditalic");j("Courier","courier","normal");j("Courier-Bold","courier",
+"bold");j("Courier-Oblique","courier","italic");j("Courier-BoldOblique","courier","bolditalic");j("Times-Roman","times","normal");j("Times-Bold","times","bold");j("Times-Italic","times","italic");j("Times-BoldItalic","times","bolditalic");G=R(M,N);T();return l};
diff --git a/files_svgedit/js/ocsvg.js b/files_svgedit/js/ocsvg.js
index d6e05754d..dd02d9f40 100644
--- a/files_svgedit/js/ocsvg.js
+++ b/files_svgedit/js/ocsvg.js
@@ -6,4 +6,24 @@ $(document).ready(function() {
});
FileActions.setDefault('image/svg+xml','Edit');
}
+ if(location.href.match(/\/files\/index\.php/)) {
+ getMimeIcon('image/svg+xml', function(icon) {
+ $('<li><p>' + t('files_svgedit', 'Graphic') + '</p></li>')
+ .attr('id', 'newSvgLi')
+ .appendTo('div#new>ul')
+ .css('background-image', 'url(' + icon + ')')
+ .data('type', 'svg')
+ .children('p')
+ .click(function() {
+ $(this).hide();
+ $('<input>').appendTo('#newSvgLi').focus().change(function() {
+ window.location = OC.filePath('files_svgedit', '', 'index.php')
+ + "?file=" + $('#dir').val() + "/" + $(this).val().replace(/(\..{3})?$/, '.svg');
+ }).blur(function() {
+ $(this).remove();
+ $('#newSvgLi>p').show();
+ });
+ });
+ });
+ }
});
diff --git a/files_svgedit/js/ocsvgEditor.js b/files_svgedit/js/ocsvgEditor.js
index 74b3dd55e..9f5b8357d 100644
--- a/files_svgedit/js/ocsvgEditor.js
+++ b/files_svgedit/js/ocsvgEditor.js
@@ -1,19 +1,28 @@
var svgCanvas = null;
+var svgString = "";
+var postFile = function(file) {
+ if(typeof(file) == 'undefined') {
+ return {filecontents: '', path: '', mtime: 0};
+ } else {
+ return {
+ filecontents: file.contents,
+ path: file.path,
+ mtime: file.mtime
+ };
+ }
+}
var ocsvg = {
frameDoc: null,
frameWin: null,
prefsShown: false,
- currentFile: {
- filecontents: '',
- path: '',
- mtime: 0
- },
- exportFile: {
- filecontents: '',
- path: '',
- mtime: 0
- },
+ currentFile: null,
+ pngFile: null,
+ pdfFile: null,
changed: false,
+ setTitle: function() {
+ var filename = ocsvg.currentFile.path.replace(/^\/(.*\/)*/, '');
+ document.title = filename + ' - ownCloud';
+ },
setEditorSize: function() {
// Fits the size of editor area to the available space
fillWindow($('#svgEditor'));
@@ -31,99 +40,62 @@ var ocsvg = {
this.currentFile.mtime = mtime;
},
setFileContentsSvg: function(svgString, e) {
+ if(e) {
+ console.log("getSvgString error:", e);
+ }
ocsvg.setFileContents('<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n' + svgString);
},
init: function(file) {
- ocsvg.setFileContents(file.contents);
- ocsvg.setFilePath(file.path);
- ocsvg.setFileMTime(file.mtime);
+ ocsvg.currentFile = new postFile(file);
+ var fileRegex = /(\..{3})?$/;
+ var ext = ['svg', 'png', 'pdf'];
+ for(var i in ext) {
+ document.getElementById(ext[i] + 'SavePath').value = file.path.replace(fileRegex, '.' + ext[i]);
+ }
},
saveFile: function(data, callback) {
- var savePath;
- if(data.force) {
- savePath = data.file.path;
- } else {
- savePath = prompt(t('files_svgedit', 'Save as'), data.file.path);
- }
- if(savePath === null || savePath == '') {
+ if(!data.file.path) {
return;
} else {
- data.file.path = savePath;
$.post(
OC.filePath('files_svgedit','ajax','save.php'),
data,
function(result) {
- if(result.status!='success'){
- // Save failed
- data.force = confirm(
- t('files_svgedit', 'Could not save:') + "\n"
- + savePath + "\n"
- + result.data.message + "\n"
- + t('files_svgedit', 'Save anyway?')
- );
- if(callback && callback.error) {
- callback.error(result);
- }
- ocsvg.saveFile(data);
- } else {
- // Save OK
- // Update mtime:
- data.file.mtime = result.data.mtime;
- if(callback && callback.success) {
- callback.success(result);
+ console.log("ajax result:", result);
+ if(result.status == 'error') {
+ if(typeof(OCdialogs) != 'undefined' && typeof(OCdialogs.confirm) == 'function') {
+ OCdialogs.confirm(
+ result.data.message + '<p>' + t('files_svgedit', 'Overwrite file?') + '</p>',
+ t('files_svgedit', 'Error'),
+ function(force) {
+ if(force) {
+ ocsvg.saveFile($.extend(data, {force: true}), callback);
+ }
+ }
+ );
+ } else {
+ if(confirm(result.data.message + '\n' + t('files_svgedit', 'Overwrite file?'))) {
+ ocsvg.saveFile($.extend(data, {force: true}), callback);
+ }
}
- alert(t('files_svgedit', 'Successfully saved!'));
+ }
+ if(typeof(callback) == 'function') {
+ callback(result);
}
},
'json'
);
}
},
- save: function(svgString, error) {
- if(error) {
- alert("Couldn't get SVG contents:\n\n" + error);
- return;
- }
- ocsvg.setFileContentsSvg(svgString);
- //saveFile
- ocsvg.saveFile(
- {
- file: ocsvg.currentFile,
- },
- {success: function(result) {ocsvg.changed = false;}}
- );
- },
- pngExport: function(svgString, error) {
- if(error) {
- alert("Couldn't get SVG contents:\n\n" + error);
- return;
- }
- // reimplementing png export is easier than trying to use svg-edit handlers...
- if(!$('#exportCanvas').length) {
- $('<canvas>', {id: 'exportCanvas'}).hide().appendTo('body');
- }
- var canvas = $('#exportCanvas')[0];
-
+ canvasRender: function(svgString, canvasSelector, callback) {
+ var canvas = $(canvasSelector)[0];
canvas.width = ocsvg.frameWin.svgCanvas.contentW;
canvas.height = ocsvg.frameWin.svgCanvas.contentH;
- $('#ocsvgBtnExport').val(t('files_svgedit', 'Rendering...'));
canvg(canvas, svgString, {renderCallback: function() {
- var datauri = canvas.toDataURL('image/png');
- $('#ocsvgBtnExport').val(t('files_svgedit', 'Export PNG'));
- if(!ocsvg.exportFile.path.length) {
- var savePath = ocsvg.currentFile.path;
- if(savePath.substr(-4) == '.svg') {
- savePath = savePath.substr(0, savePath.length - 4);
- }
- ocsvg.exportFile.path = savePath + '.png';
- }
- ocsvg.exportFile.filecontents = datauri;
- ocsvg.saveFile({
- file: ocsvg.exportFile,
- base64encoded: true,
- base64type: 'image/png'
- });
- }});
+ if(typeof(callback) == 'function') {
+ callback();
+ }
+ }});
},
changedHandler: function() {
if(!ocsvg.changed) {
@@ -140,16 +112,120 @@ var ocsvg = {
};
$(document).ready(function() {
- // set control buttons' onclick handlers:
+ // initialize UI elements:
+ $('div#svgEditorSave').tabs().dialog({
+ autoOpen: false,
+ modal: true,
+ minWidth: 400
+ });
+ // make preview divs vertically resizable:
+ //$('div#canvasPreview, div#svgtopdfPreview').resizable({handles: 's'});
+
+ // set button onclick handlers:
$('#ocsvgBtnSave').click(function() {
- svgCanvas.getSvgString()(ocsvg.save);
+ $('#svgEditorSave').dialog('open');
+ });
+ $('#svgSaveBtn').click(function() {
+ svgCanvas.getSvgString()(function(svg, error) {
+ var btn = $('#svgSaveBtn');
+ btn.val(t('files_svgedit', 'Saving...'));
+ ocsvg.setFileContentsSvg(svg);
+ ocsvg.setFilePath($('#svgSavePath').val());
+ ocsvg.saveFile({file: ocsvg.currentFile}, function(result) {
+ ocsvg.setTitle();
+ if(result.status == 'error') {
+ OCdialog.alert(result.data.message, t('files_svgedit', 'Could not save'));
+ } else {
+ if(result.status == 'success') {
+ ocsvg.changed = false;
+ ocsvg.currentFile.mtime = result.data.mtime;
+ }
+ }
+ btn.val(t('files_svgedit', 'Save'));
+ });
+ });
+ });
+ $('#svgDownloadBtn').click(function() {
+ if(ocsvg.currentFile.filecontents.length > 0) {
+ window.open('data:image/svg+xml;base64,' + Base64.encode(ocsvg.currentFile.filecontents), "svgDownloadWin");
+ }
});
- $('#ocsvgBtnExport').click(function() {
- svgCanvas.getSvgString()(ocsvg.pngExport);
+ $('#canvasRenderBtn').click(function() {
+ $('#canvasRenderBtn').val(t('files_svgedit', 'Rendering...'));
+ svgCanvas.getSvgString()(function(svg, error) {
+ ocsvg.canvasRender(svg, '#exportCanvas', function() {
+ if(ocsvg.pngFile == null) {
+ ocsvg.pngFile = new postFile();
+ }
+ ocsvg.pngFile.filecontents = $('#exportCanvas').get(0).toDataURL('image/png');
+ $('#canvasRenderBtn').val(t('files_svgedit', 'Render'));
+ });
+ });
});
+ $('#pngSaveBtn').click(function() {
+ if(ocsvg.pngFile != null) {
+ $(this).val(t('files_svgedit', 'Saving...'));
+ ocsvg.pngFile.path = $('#pngSavePath').val();
+ ocsvg.saveFile({
+ file: ocsvg.pngFile,
+ base64encoded: true,
+ base64type: 'image/png'
+ }, function(result) {
+ $('#pngSaveBtn').val(t('files_svgedit', 'Save'));
+ if(result.status == 'success') {
+ ocsvg.pngFile.mtime = result.data.mtime;
+ }
+ });
+ }
+ });
+ $('#pngDownloadBtn').click(function() {
+ if(ocsvg.pngFile.filecontents.length > 0) {
+ window.open(ocsvg.pngFile.filecontents, "exportedPngWin");
+ }
+ });
+ $('#pdfRenderBtn').click(function() {
+ var w = ocsvg.frameWin.svgCanvas.contentW * 72 / 96;
+ var h = ocsvg.frameWin.svgCanvas.contentH * 72 / 96;
+ svgCanvas.getSvgString()(function(svg, err) {
+ $('#svgtopdfPreview').empty();
+ svgString = svg;
+ var svgElement = $(svg).appendTo('#svgtopdfPreview');
+ if(ocsvg.pdfFile == null) {
+ ocsvg.pdfFile = new postFile();
+ }
+ var pdfDoc = new jsPDF('p', 'pt', [w, h]);
+ svgElementToPdf(svgElement, pdfDoc, {
+ preview: true,
+ scale: 72/96
+ });
+ ocsvg.pdfFile.filecontents = 'data:application/pdf;base64,' + Base64.encode(pdfDoc.output());
+ });
+ });
+ $('#pdfSaveBtn').click(function() {
+ if(ocsvg.pdfFile != null) {
+ $(this).val(t('files_svgedit', 'Saving...'));
+ ocsvg.pdfFile.path = $('#pdfSavePath').val();
+ ocsvg.saveFile({
+ file: ocsvg.pdfFile,
+ base64encoded: true,
+ base64type: 'application/pdf'
+ }, function(result) {
+ $('#pdfSaveBtn').val(t('files_svgedit', 'Save'));
+ if(result.status == 'success') {
+ ocsvg.pdfFile.mtime = result.data.mtime;
+ }
+ });
+ }
+ });
+ $('#pdfDownloadBtn').click(function() {
+ if(ocsvg.pdfFile.filecontents.length > 0) {
+ window.open(ocsvg.pdfFile.filecontents, "exportedPdfWin");
+ }
+ });
+
$('#ocsvgBtnClose').click(function() {
var dir = ocsvg.currentFile.path.replace(/\/[^\/]*$/, '');
- window.location = OC.linkTo('files', 'index.php') + '?dir=' + dir;
+ window.location = OC.linkTo('files', 'index.php') + (dir == '' ? '' : '?dir=') + dir;
});
// import file
@@ -158,6 +234,7 @@ $(document).ready(function() {
// set editor's size fit into the window when resizing it:
$(window).resize(function() {
ocsvg.setEditorSize();
+ //$('div#svgEditorSave').dialog('option', 'maxHeight', window.innerHeight);
}).resize();
// initialize editor frame:
@@ -172,7 +249,6 @@ $(document).ready(function() {
// fix broken color select field
ocsvg.frameDoc.find('#fill_color,#stroke_color').find('svg').css('height', '100%');
// set handler for show preferences button:
- //$('#ocsvgBtnPrefs').click(ocsvg.showPreferences);
$('#ocsvgBtnPrefs').click(function() {
ocsvg.frameDoc.find('#svg_prefs').toggle();
});
@@ -180,16 +256,23 @@ $(document).ready(function() {
ocsvg.frameDoc.find('#tool_prefs_cancel').click(function() {
ocsvg.frameDoc.find('#svg_prefs').hide();
});
+ // set handler for show properties button:
+ $('#ocsvgBtnProps').click(function() {
+ ocsvg.frameDoc.find('#svg_docprops').toggle();
+ });
+ // set handler for properties cancel button:
+ ocsvg.frameDoc.find('#tool_docprops_cancel').click(function() {
+ ocsvg.frameDoc.find('#svg_docprops').hide();
+ });
svgCanvas.setSvgString(ocsvg.currentFile.filecontents)(function(data, error) {
if(error) {
alert("Could not load file!\n\n" + error);
}
- //svgCanvas.bind('changed', ocsvg.changedHandler)();
//TODO: svgCanvas.bind doesn't work here as I expect...
ocsvg.frameWin.svgCanvas.bind('changed', ocsvg.changedHandler);
});
-
+ ocsvg.setTitle();
// set confirmation on exit (only if content has changed);
ocsvg.frameWin.onbeforeunload = ocsvg.confirmExit;
});
diff --git a/files_svgedit/js/svgToPdf.js b/files_svgedit/js/svgToPdf.js
new file mode 100644
index 000000000..bf7527859
--- /dev/null
+++ b/files_svgedit/js/svgToPdf.js
@@ -0,0 +1,251 @@
+/*
+ * svgToPdf.js
+ *
+ * Copyright 2012 Florian Hülsmann <fh@cbix.de>
+ *
+ * This script is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This script is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this file. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+var pdfSvgAttr = {
+ // allowed attributes. all others are removed if options.preview = true.
+ g: ['stroke', 'fill', 'stroke-width'],
+ line: ['x1', 'y1', 'x2', 'y2', 'stroke', 'stroke-width'],
+ rect: ['x', 'y', 'width', 'height', 'stroke', 'fill', 'stroke-width'],
+ ellipse: ['cx', 'cy', 'rx', 'ry', 'stroke', 'fill', 'stroke-width'],
+ circle: ['cx', 'cy', 'r', 'stroke', 'fill', 'stroke-width'],
+ text: ['x', 'y', 'font-size', 'font-family', 'text-anchor', 'font-weight', 'font-style', 'fill']
+};
+var svgElementToPdf = function(element, pdf, options) {
+ // pdf is a jsPDF object
+ console.log("options =", options);
+ var preview = (typeof(options.preview) == 'undefined' ? false : options.preview);
+ var k = (typeof(options.scale) == 'undefined' ? 1.0 : options.scale);
+ var colorMode = null;
+ $(element).children().each(function(i, node) {
+ //console.log("passing: ", node);
+ var n = $(node);
+ var hasFillColor = false;
+ var hasStrokeColor = false;
+ if(n.is('g,line,rect,ellipse,circle,text')) {
+ var fillColor = n.attr('fill');
+ if(typeof(fillColor) != 'undefined') {
+ var fillRGB = new RGBColor(fillColor);
+ if(fillRGB.ok) {
+ hasFillColor = true;
+ colorMode = 'F';
+ } else {
+ colorMode = null;
+ }
+ }
+ }
+ if(n.is('g,line,rect,ellipse,circle')) {
+ if(hasFillColor) {
+ pdf.setFillColor(fillRGB.r, fillRGB.g, fillRGB.b);
+ }
+ if(typeof(n.attr('stroke-width')) != 'undefined') {
+ pdf.setLineWidth(k * parseInt(n.attr('stroke-width')));
+ }
+ var strokeColor = n.attr('stroke');
+ if(typeof(strokeColor) != 'undefined') {
+ var strokeRGB = new RGBColor(strokeColor);
+ if(strokeRGB.ok) {
+ hasStrokeColor = true;
+ pdf.setDrawColor(strokeRGB.r, strokeRGB.g, strokeRGB.b);
+ if(colorMode == 'F') {
+ colorMode = 'FD';
+ } else {
+ colorMode = null;
+ }
+ } else {
+ colorMode = null;
+ }
+ }
+ }
+ switch(n.get(0).tagName.toLowerCase()) {
+ case 'svg':
+ case 'a':
+ case 'g':
+ svgElementToPdf(node, pdf, options);
+ if(preview) {
+ $.each(node.attributes, function(i, a) {
+ if(typeof(a) != 'undefined' && pdfSvgAttr.g.indexOf(a.name.toLowerCase()) == -1) {
+ node.removeAttribute(a.name);
+ }
+ });
+ }
+ break;
+ case 'line':
+ pdf.line(
+ k*parseInt(n.attr('x1')),
+ k*parseInt(n.attr('y1')),
+ k*parseInt(n.attr('x2')),
+ k*parseInt(n.attr('y2'))
+ );
+ if(preview) {
+ $.each(node.attributes, function(i, a) {
+ if(typeof(a) != 'undefined' && pdfSvgAttr.line.indexOf(a.name.toLowerCase()) == -1) {
+ node.removeAttribute(a.name);
+ }
+ });
+ }
+ break;
+ case 'rect':
+ pdf.rect(
+ k*parseInt(n.attr('x')),
+ k*parseInt(n.attr('y')),
+ k*parseInt(n.attr('width')),
+ k*parseInt(n.attr('height')),
+ colorMode
+ );
+ if(preview) {
+ $.each(node.attributes, function(i, a) {
+ if(typeof(a) != 'undefined' && pdfSvgAttr.rect.indexOf(a.name.toLowerCase()) == -1) {
+ node.removeAttribute(a.name);
+ }
+ });
+ }
+ break;
+ case 'ellipse':
+ pdf.ellipse(
+ k*parseInt(n.attr('cx')),
+ k*parseInt(n.attr('cy')),
+ k*parseInt(n.attr('rx')),
+ k*parseInt(n.attr('ry')),
+ colorMode
+ );
+ if(preview) {
+ $.each(node.attributes, function(i, a) {
+ if(typeof(a) != 'undefined' && pdfSvgAttr.ellipse.indexOf(a.name.toLowerCase()) == -1) {
+ node.removeAttribute(a.name);
+ }
+ });
+ }
+ break;
+ case 'circle':
+ pdf.circle(
+ k*parseInt(n.attr('cx')),
+ k*parseInt(n.attr('cy')),
+ k*parseInt(n.attr('r')),
+ colorMode
+ );
+ if(preview) {
+ $.each(node.attributes, function(i, a) {
+ if(typeof(a) != 'undefined' && pdfSvgAttr.circle.indexOf(a.name.toLowerCase()) == -1) {
+ node.removeAttribute(a.name);
+ }
+ });
+ }
+ break;
+ case 'text':
+ if(hasFillColor) {
+ pdf.setTextColor(fillRGB.r, fillRGB.g, fillRGB.b);
+ }
+ var fontType = "normal";
+ if(node.hasAttribute('font-weight')) {
+ if(n.attr('font-weight') == "bold") {
+ fontType = "bold";
+ } else {
+ if(preview) {
+ node.removeAttribute('font-weight');
+ }
+ }
+ }
+ if(node.hasAttribute('font-style')) {
+ if(n.attr('font-style') == "italic") {
+ if(fontType == "bold") {
+ fontType += "italic";
+ } else {
+ fontType = "italic";
+ }
+ } else {
+ if(preview) {
+ node.removeAttribute('font-style');
+ }
+ }
+ }
+ pdf.setFontType(fontType);
+ if(node.hasAttribute('font-family')) {
+ switch(n.attr('font-family').toLowerCase()) {
+ case 'serif':
+ if(preview) {
+ n.attr('font-family', 'times');
+ }
+ pdf.setFont('times');
+ break;
+ case 'monospace':
+ if(preview) {
+ n.attr('font-family', 'courier');
+ }
+ pdf.setFont('courier');
+ break;
+ default:
+ if(preview) {
+ n.attr('font-family', 'helvetica');
+ }
+ pdf.setFont('helvetica');
+ }
+ }
+ var pdfFontSize = 16;
+ if(node.hasAttribute('font-size')) {
+ pdfFontSize = k * parseInt(n.attr('font-size'));
+ if(preview) {
+ n.attr('font-size', pdfFontSize / k);
+ }
+ pdf.setFontSize(pdfFontSize);
+ }
+ var box = node.getBBox();
+ //FIXME: use more accurate positioning!!
+ var x, y, xOffset = 0;
+ if(node.hasAttribute('text-anchor')) {
+ switch(n.attr('text-anchor')) {
+ case 'end': xOffset = box.width; break;
+ case 'middle': xOffset = box.width / 2; break;
+ case 'start':
+ case 'default': break;
+ }
+ }
+ x = parseInt(n.attr('x')) - xOffset;
+ y = parseInt(n.attr('y'));
+ if(preview) {
+ n.attr('text-anchor', 'start');
+ n.attr('x', x);
+ n.attr('y', y);
+ }
+ //console.log("fontSize:", pdfFontSize, "text:", n.text());
+ pdf.text(
+ k * x,
+ k * y,
+ n.text()
+ );
+ if(preview) {
+ $.each(node.attributes, function(i, a) {
+ if(typeof(a) != 'undefined' && typeof(a.name) != 'undefined' && a.namespaceURI == null) {
+ if(pdfSvgAttr.text.indexOf(a.name.toLowerCase()) < 0) {
+ console.log("remove attr", a.nodeName, node.removeAttribute(a.nodeName));
+ }
+ }
+ });
+ }
+ break;
+ //TODO: image
+ default:
+ if(preview) {
+ console.log("can't translate to pdf:", node);
+ n.remove();
+ }
+ }
+ });
+ return pdf;
+}
diff --git a/files_svgedit/templates/editor.php b/files_svgedit/templates/editor.php
index f2e49e12f..90f7e0db0 100644
--- a/files_svgedit/templates/editor.php
+++ b/files_svgedit/templates/editor.php
@@ -9,10 +9,57 @@ var ocsvgFile = {
</script>
<div id="controls">
<input type="button" id="ocsvgBtnSave" value="<?php echo $l->t('Save'); ?>" />
- <input type="button" id="ocsvgBtnExport" value="<?php echo $l->t('Export PNG'); ?>" />
+ <input type="button" id="ocsvgBtnProps" value="<?php echo $l->t('Properties'); ?>" />
<input type="button" id="ocsvgBtnPrefs" value="<?php echo $l->t('Preferences'); ?>" />
+ <div class="separator"></div>
<input type="button" id="ocsvgBtnClose" value="<?php echo $l->t('Close'); ?>" />
</div>
<div id="svgEditor">
<iframe src="<?php echo OC_Helper::linkTo('files_svgedit', 'svg-edit/svg-editor.html'); ?>" id="svgedit"></iframe>
</div>
+<div id="svgEditorSave" title="<?php echo $l->t('Save'); ?>">
+ <ul>
+ <li><a href="#svgSave">
+ <img src="<?php echo OC_Helper::mimetypeIcon("image/svg+xml"); ?>" class="mimetypeTab" />
+ <?php echo $l->t('Save SVG'); ?>
+ </a></li>
+ <li><a href="#pngExport">
+ <img src="<?php echo OC_Helper::mimetypeIcon("image/png"); ?>" class="mimetypeTab" />
+ <?php echo $l->t('Export PNG'); ?>
+ </a></li>
+ <li><a href="#pdfExport">
+ <img src="<?php echo OC_Helper::mimetypeIcon("application/pdf"); ?>" class="mimetypeTab" />
+ <?php echo $l->t('Export PDF'); ?>
+ </a></li>
+ </ul>
+ <div id="svgSave">
+ <input type="text" id="svgSavePath" value="" />
+ <input type="button" id="svgSaveBtn" value="<?php echo $l->t('Save'); ?>" />
+ <div class="separator"></div>
+ <input type="button" id="svgDownloadBtn" value="<?php echo $l->t('Download'); ?>" />
+ </div>
+ <div id="pngExport">
+ <input type="button" id="canvasRenderBtn" value="<?php echo $l->t('Render'); ?>">
+ <div class="separator"></div>
+ <strong><?php echo $l->t('Preview:'); ?></strong>
+ <div id="canvasPreview">
+ <canvas id="exportCanvas"></canvas>
+ </div>
+ <input type="text" id="pngSavePath" value="" />
+ <input type="button" id="pngSaveBtn" value="<?php echo $l->t('Save'); ?>" />
+ <div class="separator"></div>
+ <input type="button" id="pngDownloadBtn" value="<?php echo $l->t('Download'); ?>" />
+ </div>
+ <div id="pdfExport">
+ <input type="button" id="pdfRenderBtn" value="<?php echo $l->t('Render'); ?>" />
+ <div class="separator"></div>
+ <strong><?php echo $l->t('Preview:'); ?></strong>
+ <div id="svgtopdfPreview">
+ <svg></svg>
+ </div>
+ <input type="text" id="pdfSavePath" value="" />
+ <input type="button" id="pdfSaveBtn" value="<?php echo $l->t('Save'); ?>" />
+ <div class="separator"></div>
+ <input type="button" id="pdfDownloadBtn" value="<?php echo $l->t('Download'); ?>" />
+ </div>
+</div>