http://code.google.com/p/svg-edit/
Modification for saving graphic to the server:
filesave.php (not cleaned yet...)
<?php /* * filesave.php * To be used with ext-server_opensave.js for SVG-edit * * Licensed under the Apache License, Version 2 * * Copyright(c) 2010 Alexis Deveria * */ if(!isset($_POST['output_svg']) && !isset($_POST['output_png'])) { die('post fail'); }
$file = '';
$suffix = isset($_POST['output_svg'])?'.svg':'.png';
if(isset($_POST['filename']) && strlen($_POST['filename']) > 0) { # $file = $_POST['filename'] . $suffix; $file = $_POST['filename']; #} else { # $file = 'image' . $suffix; }
if($suffix == '.svg') { $mime = 'image/svg+xml'; $contents = rawurldecode($_POST['output_svg']); } else { $mime = 'image/png'; $contents = $_POST['output_png']; $pos = (strpos($contents, 'base64,') + 7); $contents = base64_decode(substr($contents, $pos)); }
if(strpos($file, "://")===false){ $fpath = $_SERVER['DOCUMENT_ROOT'].$file; }else{ $fpath = $_SERVER['DOCUMENT_ROOT']."/img".substr($file,strrpos($file,"/")); }
$ext = substr($file, -4);
if($ext != ".svg" && $ext != ".png"){ $fh = fopen("./save.log", "a") or die("Can't open file"); fwrite($fh, "Error : ". $file . "<<<" . "\n"); fclose($fh); die("Save error: incorrect file = " . $file); }else{ $fh = fopen("./save.log", "a") or die("Can't open file"); fwrite($fh, $fpath . "<<<" . "\n"); fclose($fh); } $fh = fopen($fpath, "w") or die("Can't open file"); fwrite($fh, $contents); fclose($fh);
if($suffix == '.svg') {
$fp = str_replace(".svg", ".png", $fpath);
shell_exec("/home/extrasx/bin/rsvg-convert $fpath -o $fp") or die("convert error"); #shell_exec("rm ".$fp) or die("delete error :".$fp);
}
# header("Cache-Control: public"); # header("Content-Description: File Transfer"); # header("Content-Disposition: attachment; filename=" . $file); header("Content-Type: " . $mime); # header("Content-Transfer-Encoding: binary"); # echo $contents; ?>
ext-server_opensave.js (in extension directory, as well)
/* * ext-server_opensave.js * * Licensed under the Apache License, Version 2 * * Copyright(c) 2010 Alexis Deveria * */
svgEditor.addExtension("server_opensave", { callback: function() {
var save_svg_action = 'extensions/filesave.php'; var save_png_action = 'extensions/filesave.php'; // Create upload target (hidden iframe) var target = $('<iframe name="output_frame" src="#"/>').hide().appendTo('body'); svgEditor.setCustomHandlers({ save: function(win, data) { var svg = "<?xml version=\"1.0\"?>\n" + data; var title = svgCanvas.getDocumentTitle(); // var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_'); // var fff = svgEditor.curConfig.url; var filename = svgEditor.curConfig.url; // if(filename.indexOf('://') < 0){ // filename = '/img' + filename.substring(filename.lastIndexOf('/')); // } var form = $('<form>').attr({ method: 'post', action: save_svg_action, target: 'output_frame' }) .append('<input type="hidden" name="output_svg" value="' + encodeURI(svg) + '">') .append('<input type="hidden" name="filename" value="' + filename + '">') .appendTo('body') // .submit(); .submit().remove(); }, pngsave: function(win, data) { var issues = data.issues; if(!$('#export_canvas').length) { $('<canvas>', {id: 'export_canvas'}).hide().appendTo('body'); } var c = $('#export_canvas')[0]; c.width = svgCanvas.contentW; c.height = svgCanvas.contentH; canvg(c, data.svg, {renderCallback: function() { var datauri = c.toDataURL('image/png'); var uiStrings = svgEditor.uiStrings; var note = ''; // Check if there's issues if(issues.length) { var pre = "\n \u2022 "; note += ("\n\n" + pre + issues.join(pre)); } if(note.length) { alert(note); } var title = svgCanvas.getDocumentTitle(); var filename = title.replace(/[^a-z0-9\.\_\-]+/gi, '_'); var form = $('<form>').attr({ method: 'post', action: save_png_action, target: 'output_frame' }) .append('<input type="hidden" name="output_png" value="' + datauri + '">') .append('<input type="hidden" name="filename" value="' + filename + '">') .appendTo('body') .submit().remove(); }}); } }); // Do nothing if client support is found if(window.FileReader) return; var cancelled = false; // Change these to appropriate script file var open_svg_action = 'extensions/fileopen.php?type=load_svg'; var import_svg_action = 'extensions/fileopen.php?type=import_svg'; var import_img_action = 'extensions/fileopen.php?type=import_img'; // Set up function for PHP uploader to use svgEditor.processFile = function(str64, type) { if(cancelled) { cancelled = false; return; } $('#dialog_box').hide(); if(type != 'import_img') { var xmlstr = svgCanvas.Utils.decode64(str64); } switch ( type ) { case 'load_svg': svgCanvas.clear(); svgCanvas.setSvgString(xmlstr); svgEditor.updateCanvas(); break; case 'import_svg': svgCanvas.importSvgString(xmlstr); svgEditor.updateCanvas(); break; case 'import_img': svgCanvas.setGoodImage(str64); break; } } // Create upload form var open_svg_form = $('<form>'); open_svg_form.attr({ enctype: 'multipart/form-data', method: 'post', action: open_svg_action, target: 'output_frame' }); // Create import form var import_svg_form = open_svg_form.clone().attr('action', import_svg_action); // Create image form var import_img_form = open_svg_form.clone().attr('action', import_img_action); // It appears necessory to rebuild this input every time a file is // selected so the same file can be picked and the change event can fire. function rebuildInput(form) { form.empty(); var inp = $('<input type="file" name="svg_file">').appendTo(form); function submit() { // This submits the form, which returns the file data using svgEditor.uploadSVG form.submit(); rebuildInput(form); $.process_cancel("Uploading...", function() { cancelled = true; $('#dialog_box').hide(); }); } if(form[0] == open_svg_form[0]) { inp.change(function() { // This takes care of the "are you sure" dialog box svgEditor.openPrep(function(ok) { if(!ok) { rebuildInput(form); return; } submit(); }); }); } else { inp.change(function() { // This submits the form, which returns the file data using svgEditor.uploadSVG submit(); }); } } // Create the input elements rebuildInput(open_svg_form); rebuildInput(import_svg_form); rebuildInput(import_img_form);
// Add forms to buttons $("#tool_open").show().prepend(open_svg_form); $("#tool_import").show().prepend(import_svg_form); $("#tool_image").prepend(import_img_form); } });
Additional elements for showing PNG (converted from SVG as needed)
- Rewriterule is used for detecting the abscence of PNG and presence of SVG to convert the SVG into PNG, as needed.
.htaccess
RewriteEngine on
RewriteCond %{HTTP:REDIRECT_STATUS} !^$ RewriteRule ^ - [L]
RewriteCond %{REQUEST_FILENAME} \.png$ RewriteCond %{REQUEST_FILENAME} !-f #RewriteRule ^(.+)\.png$ /$1.svg?xxx=$1 [R=302,E=SVG:$1] RewriteRule ^(.+)\.png$ /$1.svg [C,E=SVG:$1]
RewriteCond %{REQUEST_FILENAME} \.svg$ RewriteCond /home/mini%{REQUEST_FILENAME} -f RewriteRule ^(.+)$ /rsvg.cgi?$1 [L]
rsvg.cgi
#!/bin/sh
F=.$QUERY_STRING FP=${F%.svg}.png $HOME/bin/rsvg-convert $F -o $FP echo "Content-type: image/png " cat $FP
compiled rsvg-convert from the source using the method similar to this:
If you want the binary, you can contact me via PM in ILP