Implement serialization, clipboard

This commit is contained in:
Maik Macho 2017-11-21 22:24:25 +01:00
parent 31613aa412
commit 6831781569
No known key found for this signature in database
GPG Key ID: 21C91DB3ADE0B6D5
9 changed files with 151 additions and 5 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules/
builds/
package-lock.json

View File

@ -9,6 +9,7 @@
<script type="text/javascript" src="scripts/keyboard.js"></script>
<script type="text/javascript" src="scripts/guide.js"></script>
<script type="text/javascript" src="scripts/render.js"></script>
<script type="text/javascript" src="scripts/serializer.js"></script>
<script type="text/javascript" src="scripts/theme.js"></script>
<script type="text/javascript" src="scripts/interface.js"></script>
<link rel="stylesheet" type="text/css" href="links/reset.css"/>
@ -31,6 +32,8 @@
document.addEventListener('mousedown', function(e){ dotgrid.mouse_down(e); }, false);
document.addEventListener('mousemove', function(e){ dotgrid.mouse_move(e); }, false);
document.addEventListener('mouseup', function(e){ dotgrid.mouse_up(e);}, false);
document.addEventListener('copy', function(e){ dotgrid.copy(e);}, false);
document.addEventListener('paste', function(e){ dotgrid.paste(e);}, false);
</script>
</div>
</body>

View File

@ -44,6 +44,7 @@ function Dotgrid(width,height,grid_x,grid_y,block_x,block_y,thickness = 3,lineca
this.guide = new Guide();
this.render = new Render();
this.serializer = new Serializer();
this.path = document.createElementNS("http://www.w3.org/2000/svg", "path");
this.segments = [];
@ -479,6 +480,47 @@ function Dotgrid(width,height,grid_x,grid_y,block_x,block_y,thickness = 3,lineca
});
}
this.copy = function(e)
{
if(this.segments.length == 0){ return; }
this.scale = 1
this.width = 300
this.height = 300
this.draw()
var svg = this.svg_el.outerHTML
e.clipboardData.items.add(JSON.stringify({ dotgrid: this.serializer.serialize() }), "text/plain");
e.clipboardData.items.add(svg, "text/html");
e.clipboardData.items.add(svg, "text/svg+xml");
// Right now, the following doesn't work and breaks "text/plain".
// This seems to be a bug in Chromium as others around the web complain, too.
/*
e.clipboardData.items.add(new File([new Blob([svg], { type: "image/svg+xml" } )], "image.svg"));
e.clipboardData.items.add(new File([new Blob([Uint8Array.from(dotgrid.render.buffer()).buffer], { type: "image/png" } ) ], "image.png"));
*/
e.preventDefault();
}
this.paste = function(e)
{
var data = e.clipboardData.getData("text/plain");
try {
data = JSON.parse(data.trim()).dotgrid;
if (!data) throw null;
} catch (err) {
// Not a dotgrid JSON.
return;
}
this.serializer.deserialize(data);
this.resize();
this.draw();
}
// Normalizers
this.position_in_grid = function(pos)

View File

@ -1,5 +1,6 @@
function Path_Arc(from,to,orientation,end)
{
this.__serialized_name__ = "Path_Arc";
this.name = "arc";
this.from = from;

View File

@ -1,5 +1,6 @@
function Path_Bezier(from,to,end)
{
this.__serialized_name__ = "Path_Bezier";
this.name = "bezier";
this.from = from;

View File

@ -1,5 +1,6 @@
function Path_Close()
{
this.__type_ = "Path_Close";
this.name = "close";
this.to_segment = function(prev)

View File

@ -1,5 +1,6 @@
function Path_Line(from,to,end = null)
{
this.__serialized_name__ = "Path_Line";
this.name = "line";
this.from = from;

View File

@ -1,5 +1,6 @@
function Pos(x,y)
{
this.__serialized_name__ = ".";
this.x = x;
this.y = y;
@ -40,3 +41,7 @@ function Pos(x,y)
function clamp(v, min, max) { return v < min ? min : v > max ? max : v; }
}
// This is ugly, but Pos.__serialized_name__ == ".";
// Let's keep the character count low.
window["."] = Pos;

View File

@ -0,0 +1,91 @@
function Serializer()
{
var __data_segments__ = 0;
var __data_thickness__ = 1;
var __data_linecap__ = 2;
var __data_color__ = 3;
var __data_mirror_index__ = 4;
var __data_fill__ = 5;
this.serialize = function()
{
// Store the data in an array.
// This keeps away the property names, which just clutter up everything.
var data = [
[],
dotgrid.thickness,
dotgrid.linecap,
dotgrid.color,
dotgrid.mirror_index,
dotgrid.fill
];
for (var id in dotgrid.segments) {
data[__data_segments__][id] = this.serialize_segment(dotgrid.segments[id]);
}
return data;
}
this.deserialize = function(data)
{
if (data[__data_segments__]) {
for (var id in data[__data_segments__]) {
data[__data_segments__][id] = this.deserialize_segment(data[__data_segments__][id]);
}
}
var d = (index, fallback) => index < data.length ? data[index] : fallback;
dotgrid.segments = d(__data_segments__, []);
dotgrid.thickness = d(__data_thickness__, 10);
dotgrid.linecap = d(__data_linecap__, "square");
dotgrid.color = d(__data_color__, "#000000");
dotgrid.mirror_index = d(__data_mirror_index__, 0);
dotgrid.fill = d(__data_fill__, false);
}
this.serialize_segment = function(s) {
// Return falsy values (null, 0, false, "", ...) directly.
if (!s) return s;
var data = [";"];
// Get rid of non-serializable stuff (i.e. functions).
s = JSON.parse(JSON.stringify(s));
// Store everything in arrays instead of objects, saving characters.
for (var id in s) {
// Skip the non-serialzied path name.
if (s.__serialized_name__ && id === "name")
continue;
var prop = s[id];
if (typeof(prop) === "object") {
prop = this.serialize_segment(prop);
}
data.push(prop);
}
return data;
}
this.deserialize_segment = function(data) {
var name = data.splice(0, 2)[1];
// Unserialize anything that's serialized.
for (var id in data) {
var prop = data[id];
if (prop && typeof(prop) === "object" && prop.length && prop[0] === ";") {
prop = this.deserialize_segment(prop);
}
data[id] = prop;
}
var s = {};
window[name].apply(s, data);
return s;
}
}