diff options
author | Florian Hülsmann <fh@cbix.de> | 2012-04-19 03:46:45 +0400 |
---|---|---|
committer | Florian Hülsmann <fh@cbix.de> | 2012-04-19 03:46:45 +0400 |
commit | 5c39f659c656e285791ebde64d9ec8120f45406e (patch) | |
tree | cb1dbd968f4410872a8bd2356a073299a69db425 /files_svgedit | |
parent | 824a57042b31277570a3dd6e713ea3aa9143ea70 (diff) |
updated from sourceforge repo
Diffstat (limited to 'files_svgedit')
-rw-r--r-- | files_svgedit/README | 20 | ||||
-rw-r--r-- | files_svgedit/RELEASE | 24 | ||||
-rw-r--r-- | files_svgedit/ROADMAP | 13 | ||||
-rw-r--r-- | files_svgedit/ajax/save.php | 12 | ||||
-rw-r--r-- | files_svgedit/appinfo/info.xml | 4 | ||||
-rw-r--r-- | files_svgedit/css/ocsvg.css | 30 | ||||
-rw-r--r-- | files_svgedit/index.php | 6 | ||||
-rw-r--r-- | files_svgedit/js/base64.js | 143 | ||||
-rw-r--r-- | files_svgedit/js/jsPDF/MIT-LICENSE.txt | 20 | ||||
-rw-r--r-- | files_svgedit/js/jsPDF/README | 3 | ||||
-rw-r--r-- | files_svgedit/js/jsPDF/jspdf.js | 756 | ||||
-rwxr-xr-x | files_svgedit/js/jsPDF/jspdf.min.js | 57 | ||||
-rw-r--r-- | files_svgedit/js/ocsvg.js | 20 | ||||
-rw-r--r-- | files_svgedit/js/ocsvgEditor.js | 263 | ||||
-rw-r--r-- | files_svgedit/js/svgToPdf.js | 251 | ||||
-rw-r--r-- | files_svgedit/templates/editor.php | 49 |
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> |