Commit 97c2c93e authored by Bruce Bligny's avatar Bruce Bligny

Merge branch 'master' of gitlab.com:osp-kitchen/workshop_esad-amiens_giants

parents 717737f9 abd97060
......@@ -76,3 +76,13 @@ No, it is a programming framework.
* For which operating systems is this tool available?
Applications made with Electron can be run on Linux, Mac and Windows. It's one of the essential features of the tool.
To test Electron I wrapped the TTX-inspector developed for the ['Dirty Variables' workshop](https://gitlab.constantvzw.org/osp/workshop.dirty-variables/tree/master/inspector) into an application.
![](images/electron-A.png)
![](images/electron-B.png)
![](images/electron-C.png)
![](images/electron-D.png)
\ No newline at end of file
......@@ -14,75 +14,98 @@ Tags: maps, command line, vector, dithering, (! tags are multiple)
## VectoriaL EditingG
![](images/mona.svg)
* Who is developing the tool?
Ted Gould, Bryce Harrington, Nathan Hurst, MenTaLguY
and many different people on list below > https://inkscape.org/fr/credits/
and many different people on list below https://inkscape.org/fr/credits/
* Is the tool under active development?
It seems not, but developer are working to improve it
* When did the development of the tool start? / How old is the software?
It start in 2003 (a fork of Sodipodi)
* Does the tool have a Wikipedia page?
https://fr.wikipedia.org/wiki/Inkscape
* What is the tool made for?
Drawing, vectorial editing
* Who is the tool made for?
for graphic designers, artists or every person wich are interest in it, ab d all people with a computer
For graphic designers, artists or every person wich are interest in it, ab d all people with a computer
* Wat is the license of the tool?
GPL License / GNU GENERAL PUBLIC LICENSE
* Is it possible to contribute to the tool? How? How many people are contributing?
Yes, by writing Core Inkscape code, writing inkscape extensions, packaging inkscape, testing it, reporting bugs, translating inkscape software and website and promote it
* What does the tool cost? Is it a one time payment or a subscription model?
It cost nothing, to my knowledge
* Are there tools alike? What makes this tool different?
Yes it is like Adobe Illustrator, CorelDRAW
* Does the tool have a Graphical Interface?
yes
* Is the interface clear?
yes
* Is the interface looking like other applications or is it custom made?
It look like some "old" application coming back from past or future
* Does the tool have a command line interface / can you use the tool from the commandline?
yes, but mightbe not on mac
* Can you automate the tool? Does the tool have a scripting interface / API?
maybe but for now i don't know how
* What are the filetypes the tool can read?
PNG, SVG, JPEG, ...
* What are the filetypes the tool can generate / export?
SVG
* Is there an official documentation and if so where?
https://inkscape.org/fr/apprendre/
* For which operating systems is this tool available?
Windows, mac OS, Linux / GNU
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Glyph</title>
<style>
.controls {
position: fixed;
top: 0;
right: 0;
left: 0;
padding: 10px;
background: #efefef;
}
body {
padding-top: 20px;
}
</style>
</head>
<body>
<section class="controls">
<!-- <label>Font file:
<input type="file" id="font-selector" />
</label> -->
<button id="select-font">Select a TTX</button>
<button id="reload-font">Reload font</button>
<button id="export-canvas">Export Canvas</button>
<select id="glyph-selector"></select>
</section>
<canvas id="canvas" width="1000" height="1000"></canvas>
<script src="ttxInspector.js"></script>
</body>
</html>
\ No newline at end of file
const { app, BrowserWindow } = require('electron')
const path = require('path')
const url = require('url')
function createWindow() {
win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
\ No newline at end of file
{
"name": "tutorial",
"version": "0.1.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"devDependencies": {
"electron": "^1.8.4"
}
}
const fs = require('fs');
const { dialog } = require('electron').remote
var font;
class Font {
constructor(xml) {
this.xml = xml;
let parser = new DOMParser();
this.dom = parser.parseFromString(xml, 'text/xml');
}
table(name) { return this.dom.querySelector(name) };
glyphs() { return this.table('glyf').querySelectorAll('TTGlyph'); };
glyph(name) { return this.table('glyf').querySelector(`TTGlyph[name="${name}"]`); };
variations() { return this.table('fvar'); };
glyphVariations() { return this.table('gvar').querySelectorAll('glyphVariations'); };
glyphVariation(name) { return this.table('gvar').querySelector(`glyphVariations[glyph="${name}"]`); };
delta(name, point) { return this.glyphVariation(name).querySelectorAll(`delta[pt="${point}"]`); };
contours(name) { return this.glyph(name).querySelectorAll('contour'); };
}
function deriveCurvePoint(p1, p2) {
return {
'x': p1.x + .5 * (p2.x - p1.x),
'y': p1.y + .5 * (p2.y - p1.y),
'on': false,
'derived': true
};
}
function drawGlyph(name, font) {
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
var glyph = font.glyph(name);
var xmin = glyph.getAttribute('xMin'),
xmax = glyph.getAttribute('xMax'),
ymin = glyph.getAttribute('yMin'),
ymax = glyph.getAttribute('yMax'),
glyphWidth = xmax - xmin,
glyphHeight = ymax - ymin;
prepareCanvas = (ctx) => {
ctx.transform(1, 0, 0, -1, 0, canvas.height);
ctx.translate((canvas.width - glyphWidth) / 2 - xmin, (canvas.height - glyphHeight) / 2);
};
ctx.save();
prepareCanvas(ctx);
var glyphTTYPoints = [];
font.contours(name).forEach(contour => {
ctx.beginPath();
var contourTTYPoints = [];
var curvepoints = [];
contour.querySelectorAll('pt').forEach((point) => {
var x = parseInt(point.getAttribute('x')),
y = parseInt(point.getAttribute('y')),
on = (point.getAttribute('on') === "1") ? true : false;
contourTTYPoints.push({
'x': x,
'y': y,
'on': on
});
});
var prevPoint = contourTTYPoints[contourTTYPoints.length - 1];
for (var i = 0; i < contourTTYPoints.length; i++) {
var point = contourTTYPoints[i];
if (!point.on) {
if (!prevPoint.on) {
curvepoints.push(deriveCurvePoint(point, prevPoint));
} else if (i === 0) {
curvepoints.push(prevPoint);
}
}
curvepoints.push(point);
prevPoint = point;
}
if (!curvepoints[curvepoints.length - 1].on) {
curvepoints.push(curvepoints[0]);
}
for (var i = 0; i < curvepoints.length; i++) {
var p = curvepoints[i];
if (p.on) {
if (i === 0) {
ctx.moveTo(p.x, p.y);
} else {
ctx.lineTo(p.x, p.y);
}
} else {
var cp = p,
p = curvepoints[i + 1];
ctx.quadraticCurveTo(cp.x, cp.y, p.x, p.y);
i++;
}
}
ctx.closePath();
ctx.stroke();
glyphTTYPoints = glyphTTYPoints.concat(contourTTYPoints);
});
// Mark points
ctx.save();
ctx.strokeStyle = 'darkblue';
ctx.fillStyle = 'darkblue'
glyphTTYPoints.forEach((p, k) => {
ctx.beginPath();
ctx.arc(p.x, p.y, 3, 0, 2 * Math.PI, false);
if (p.on) {
ctx.fill();
} else {
ctx.stroke();
}
ctx.save();
ctx.strokeStyle = 'orange';
ctx.fillStyle = 'orange';
font.delta(name, k).forEach((d) => {
var x = p.x, y = p.y, dx = parseInt(d.getAttribute('x')), dy = parseInt(d.getAttribute('y'));
if (dx !== 0 || dy !== 0) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + dx, y + dy);
ctx.stroke();
arrowHead(ctx, x + dx, y + dy, calcAngle(dx, dy), 10);
}
ctx.beginPath();
ctx.arc(x + dx, y + dy, 2, 0, Math.PI * 2, false);
ctx.fill();
});
ctx.restore();
});
ctx.restore();
ctx.restore();
}
function fillGlyphSelector(selected) {
var glyphSelector = document.getElementById('glyph-selector');
while (glyphSelector.firstChild) {
glyphSelector.removeChild(glyphSelector.firstChild);
}
font.glyphs().forEach((glyph) => {
var option = document.createElement('option');
option.value = glyph.getAttribute('name');
option.appendChild(document.createTextNode(option.value));
if (selected && option.value === selected) {
option.selected = true;
}
glyphSelector.appendChild(option);
});
}
function arrowHead(ctx, x, y, angle, size) {
ctx.save();
ctx.translate(x, y);
// ctx.arc(0, 0, 10, 0, 2 * Math.PI, false);
// // ctx.stroke();
ctx.rotate(angle + Math.PI * .75);
ctx.scale(size / 10, size / 10);
ctx.beginPath();
ctx.moveTo(3, 10);
ctx.lineTo(0, 0);
ctx.lineTo(10, 3);
// ctx.endPath();
ctx.stroke();
ctx.restore();
}
function calcAngle(dx, dy) {
return Math.atan(dy / dx) + ((dx < 0) ? Math.PI : 0);
}
function loadTTX(path) {
const xml = fs.readFileSync(path);
font = new Font(xml);
const selectedGlyph = localStorage.getItem('TTXInspectoreSelectedGlyph');
fillGlyphSelector(selectedGlyph);
if (selectedGlyph) {
drawGlyph(selectedGlyph, font);
}
}
function loadFont() {
var paths = dialog.showOpenDialog({ properties: ['openFile'], filters: [{ name: 'ttx', extensions: ['ttx'] }] });
if (paths && paths.length > 0) {
const path = paths[0];
localStorage.setItem('TTXInspectorFontPath', path);
localStorage.removeItem('TTXInspectoreSelectedGlyph');
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
loadTTX(path);
}
}
function loadFromStorage() {
const path = localStorage.getItem('TTXInspectorFontPath')
if (path) {
loadTTX(path);
}
}
document.getElementById('select-font').addEventListener('click', loadFont);
document.getElementById('glyph-selector').addEventListener('change', function () {
var value = this.value;
localStorage.setItem('TTXInspectoreSelectedGlyph', value);
drawGlyph(value, font);
});
document.getElementById('export-canvas').addEventListener('click', () => {
const canvas = document.getElementById('canvas'),
path = dialog.showSaveDialog({});
reader = new FileReader();
reader.onload = function () {
fs.writeFileSync(path, Buffer.from(this.result));
}
if (path) {
canvas.toBlob((blob) => {
reader.readAsArrayBuffer(blob);
}, 'image/png');
}
});
document.getElementById('reload-font').addEventListener('click', loadFromStorage);
loadFromStorage();
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment