- // ==UserScript==
- // @name vectorizer.ai
- // @version 0.0.1
- // @description vectorizer.ai free download
- // @icon https://d1j8j7mb8gx2ao.cloudfront.net/p/assets/logos/vectorizer-ai-logo_1c2b7a3ae82c1def79ab4c0e9cc83bcc.svg
-
- // @author ml98
- // @namespace http://tampermonkey.net/
- // @license MIT
-
- // @match https://vectorizer.ai/images/*
- // @grant none
- // @run-at document-start
- // ==/UserScript==
-
- let state = 0;
- let data = { width: 1, height: 1, curves: [], style: {} };
-
- function proxy_functions(object, apply = (f, _this, args) => f.apply(_this, args)) {
- const descriptors = Object.getOwnPropertyDescriptors(object);
- Object.keys(descriptors).filter(
- (name) => descriptors[name].value instanceof Function
- ).forEach((f) => {
- object[f] = new Proxy(object[f], { apply });
- });
- }
-
- function path2svg(name, args) {
- switch (name) {
- case "moveTo": {
- let [x, y] = args;
- return `M${x} ${y}`;
- }
- case "lineTo": {
- let [x, y] = args;
- return `L${x} ${y}`;
- }
- case "ellipse": {
- let [cx, cy, rx, ry, rotation, theta1, theta2, ccw] = args;
- let dx = rx * Math.cos(theta2), dy = ry * Math.sin(theta2);
- let c = Math.cos(rotation), s = Math.sin(rotation);
- let ex= cx + c * dx - s * dy, ey = cy + s * dx + c * dy;
- let angle = rotation * (180 / Math.PI);
- let large_arc = (theta2 - theta1) % (2 * Math.PI) > Math.PI ? 1 : 0;
- let sweep = ccw ? 0 : 1;
- return `A${rx} ${ry} ${angle} ${large_arc} ${sweep} ${ex} ${ey}`;
- }
- case "bezierCurveTo": {
- let [cp1x, cp1y, cp2x, cp2y, x, y] = args;
- return `C${cp1x} ${cp1y} ${cp2x} ${cp2y} ${x} ${y}`;
- }
- case "quadraticCurveTo": {
- let [cpx, cpy, x, y] = args;
- return `Q${cpx} ${cpy} ${x} ${y}`;
- }
- case "closePath": {
- return `Z`;
- }
- default: {
- // throw new Error("unimplemented path", name);
- return ``;
- }
- }
- }
-
- proxy_functions(Path2D.prototype, (f, _this, args) => {
- _this.s ??= "";
- // _this.s += `${f.name}[${args.toString()}] `;
- _this.s += path2svg(f.name, args);
- return f.apply(_this, args);
- });
-
- proxy_functions(CanvasRenderingContext2D.prototype, (f, _this, args) => {
- if(_this.canvas.id) {
- // width, height
- }
- if(!_this.canvas.id) {
- switch(f.name) {
- case 'drawImage':
- if(state == 0) {
- data.width = args[3];
- data.height = args[4];
- state = 1;
- }
- break;
- case 'clip':
- if(state == 1) {
- // console.log(_this.lineWidth, _this.lineJoin);
- data.curves = [];
- data.style = { lineWidth: _this.lineWidth, lineJoin: _this.lineJoin };
- state = 2;
- }
- break;
- case 'fill':
- if(state == 2) {
- // console.log(f.name, _this.fillStyle, args[0].s);
- if(!args[0].s) {
- state = 1;
- }
- data.curves.push({fill: _this.fillStyle, d: args[0].s});
- }
- break;
- case 'stroke':
- if(state == 2) {
- // console.log(f.name, _this.strokeStyle, args[0].s);
- if(!args[0].s) {
- state = 1;
- }
- data.curves.push({stroke: _this.strokeStyle, d: args[0].s});
- }
- break;
- case 'restore':
- if(state == 2) {
- state = 3;
- console.log(data);
- create_download_button();
- }
- break;
- }
- }
- return f.apply(_this, args);
- });
-
- function svg_element(tag, attributes) {
- const element = document.createElementNS('http://www.w3.org/2000/svg', tag);
- for (let attr in attributes) {
- element.setAttribute(attr, attributes[attr]);
- }
- return element;
- }
-
- function create_svg() {
- const { width, height, curves, style } = data;
- const svg = svg_element('svg', {
- xmlns: 'http://www.w3.org/2000/svg',
- viewBox: `0 0 ${width} ${height}`,
- width,
- height,
- });
-
- curves.forEach(({d, fill, stroke}) => {
- const path = fill ? {d, fill, stroke: fill} : {d, stroke};
- const element = svg_element('path', path);
- svg.appendChild(element);
- });
-
- return svg;
- }
-
- function create_download_button() {
- const svg = create_svg();
- const content = new XMLSerializer().serializeToString(svg);
- const type = 'image/svg+xml';
- const url = URL.createObjectURL(new Blob([content], {type}));
-
- const button = document.querySelector('#App-DownloadLink');
- const a = button.cloneNode(true);
- button.before(a);
- a.style.borderRadius = 0;
- a.querySelector('.showPaid').style.display = 'none';
- a.querySelector('.showFree').style.display = 'inline';
- a.href = url;
- a.target = '_blank';
- a.download = 'result.svg';
- }