Skip to content

Commit 0225355

Browse files
authored
Merge pull request #72 from pshihn/dev
Typescript port
2 parents a0042a0 + cb7aefc commit 0225355

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

82 files changed

+16539
-6751
lines changed

.babelrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"presets": [
3+
"es2015"
4+
],
5+
"plugins": [
6+
"external-helpers"
7+
]
8+
}

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
.cache
22
.DS_Store
3-
z
4-
node_modules
3+
node_modules
4+
z

bin/canvas-async.d.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { RoughCanvas } from './canvas';
2+
import { Config, Options, Drawable } from './core';
3+
import { RoughGeneratorAsync } from './generator-async';
4+
import { Point } from './geometry';
5+
export declare class RoughCanvasAsync extends RoughCanvas {
6+
private genAsync;
7+
constructor(canvas: HTMLCanvasElement, config?: Config);
8+
readonly generator: RoughGeneratorAsync;
9+
line(x1: number, y1: number, x2: number, y2: number, options?: Options): Promise<Drawable>;
10+
rectangle(x: number, y: number, width: number, height: number, options?: Options): Promise<Drawable>;
11+
ellipse(x: number, y: number, width: number, height: number, options?: Options): Promise<Drawable>;
12+
circle(x: number, y: number, diameter: number, options?: Options): Promise<Drawable>;
13+
linearPath(points: Point[], options?: Options): Promise<Drawable>;
14+
polygon(points: Point[], options?: Options): Promise<Drawable>;
15+
arc(x: number, y: number, width: number, height: number, start: number, stop: number, closed?: boolean, options?: Options): Promise<Drawable>;
16+
curve(points: Point[], options?: Options): Promise<Drawable>;
17+
path(d: string, options?: Options): Promise<Drawable>;
18+
}

bin/canvas-async.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { RoughCanvas } from './canvas';
2+
import { RoughGeneratorAsync } from './generator-async';
3+
export class RoughCanvasAsync extends RoughCanvas {
4+
constructor(canvas, config) {
5+
super(canvas, config);
6+
this.genAsync = new RoughGeneratorAsync(config || null, this.canvas);
7+
}
8+
// @ts-ignore
9+
get generator() {
10+
return this.genAsync;
11+
}
12+
// @ts-ignore
13+
async line(x1, y1, x2, y2, options) {
14+
const d = await this.genAsync.line(x1, y1, x2, y2, options);
15+
this.draw(d);
16+
return d;
17+
}
18+
// @ts-ignore
19+
async rectangle(x, y, width, height, options) {
20+
const d = await this.genAsync.rectangle(x, y, width, height, options);
21+
this.draw(d);
22+
return d;
23+
}
24+
// @ts-ignore
25+
async ellipse(x, y, width, height, options) {
26+
const d = await this.genAsync.ellipse(x, y, width, height, options);
27+
this.draw(d);
28+
return d;
29+
}
30+
// @ts-ignore
31+
async circle(x, y, diameter, options) {
32+
const d = await this.genAsync.circle(x, y, diameter, options);
33+
this.draw(d);
34+
return d;
35+
}
36+
// @ts-ignore
37+
async linearPath(points, options) {
38+
const d = await this.genAsync.linearPath(points, options);
39+
this.draw(d);
40+
return d;
41+
}
42+
// @ts-ignore
43+
async polygon(points, options) {
44+
const d = await this.genAsync.polygon(points, options);
45+
this.draw(d);
46+
return d;
47+
}
48+
// @ts-ignore
49+
async arc(x, y, width, height, start, stop, closed = false, options) {
50+
const d = await this.genAsync.arc(x, y, width, height, start, stop, closed, options);
51+
this.draw(d);
52+
return d;
53+
}
54+
// @ts-ignore
55+
async curve(points, options) {
56+
const d = await this.genAsync.curve(points, options);
57+
this.draw(d);
58+
return d;
59+
}
60+
// @ts-ignore
61+
async path(d, options) {
62+
const drawing = await this.genAsync.path(d, options);
63+
this.draw(drawing);
64+
return drawing;
65+
}
66+
}

bin/canvas.d.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Config, Options, Drawable } from './core';
2+
import { RoughGenerator } from './generator';
3+
import { RoughRenderer } from './renderer';
4+
import { Point } from './geometry';
5+
export declare class RoughCanvas {
6+
protected canvas: HTMLCanvasElement;
7+
protected ctx: CanvasRenderingContext2D;
8+
private gen;
9+
constructor(canvas: HTMLCanvasElement, config?: Config);
10+
readonly generator: RoughGenerator;
11+
static createRenderer(): RoughRenderer;
12+
line(x1: number, y1: number, x2: number, y2: number, options?: Options): Drawable;
13+
rectangle(x: number, y: number, width: number, height: number, options?: Options): Drawable;
14+
ellipse(x: number, y: number, width: number, height: number, options?: Options): Drawable;
15+
circle(x: number, y: number, diameter: number, options?: Options): Drawable;
16+
linearPath(points: Point[], options?: Options): Drawable;
17+
polygon(points: Point[], options?: Options): Drawable;
18+
arc(x: number, y: number, width: number, height: number, start: number, stop: number, closed?: boolean, options?: Options): Drawable;
19+
curve(points: Point[], options?: Options): Drawable;
20+
path(d: string, options?: Options): Drawable;
21+
draw(drawable: Drawable): void;
22+
private computeBBox;
23+
private fillSketch;
24+
private _drawToContext;
25+
}

bin/canvas.js

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import { RoughGenerator } from './generator';
2+
import { RoughRenderer } from './renderer';
3+
const hasDocument = typeof document !== 'undefined';
4+
export class RoughCanvas {
5+
constructor(canvas, config) {
6+
this.canvas = canvas;
7+
this.ctx = this.canvas.getContext('2d');
8+
this.gen = new RoughGenerator(config || null, this.canvas);
9+
}
10+
get generator() {
11+
return this.gen;
12+
}
13+
static createRenderer() {
14+
return new RoughRenderer();
15+
}
16+
line(x1, y1, x2, y2, options) {
17+
const d = this.gen.line(x1, y1, x2, y2, options);
18+
this.draw(d);
19+
return d;
20+
}
21+
rectangle(x, y, width, height, options) {
22+
const d = this.gen.rectangle(x, y, width, height, options);
23+
this.draw(d);
24+
return d;
25+
}
26+
ellipse(x, y, width, height, options) {
27+
const d = this.gen.ellipse(x, y, width, height, options);
28+
this.draw(d);
29+
return d;
30+
}
31+
circle(x, y, diameter, options) {
32+
const d = this.gen.circle(x, y, diameter, options);
33+
this.draw(d);
34+
return d;
35+
}
36+
linearPath(points, options) {
37+
const d = this.gen.linearPath(points, options);
38+
this.draw(d);
39+
return d;
40+
}
41+
polygon(points, options) {
42+
const d = this.gen.polygon(points, options);
43+
this.draw(d);
44+
return d;
45+
}
46+
arc(x, y, width, height, start, stop, closed = false, options) {
47+
const d = this.gen.arc(x, y, width, height, start, stop, closed, options);
48+
this.draw(d);
49+
return d;
50+
}
51+
curve(points, options) {
52+
const d = this.gen.curve(points, options);
53+
this.draw(d);
54+
return d;
55+
}
56+
path(d, options) {
57+
const drawing = this.gen.path(d, options);
58+
this.draw(drawing);
59+
return drawing;
60+
}
61+
draw(drawable) {
62+
const sets = drawable.sets || [];
63+
const o = drawable.options || this.gen.defaultOptions;
64+
const ctx = this.ctx;
65+
for (const drawing of sets) {
66+
switch (drawing.type) {
67+
case 'path':
68+
ctx.save();
69+
ctx.strokeStyle = o.stroke;
70+
ctx.lineWidth = o.strokeWidth;
71+
this._drawToContext(ctx, drawing);
72+
ctx.restore();
73+
break;
74+
case 'fillPath':
75+
ctx.save();
76+
ctx.fillStyle = o.fill || '';
77+
this._drawToContext(ctx, drawing);
78+
ctx.restore();
79+
break;
80+
case 'fillSketch':
81+
this.fillSketch(ctx, drawing, o);
82+
break;
83+
case 'path2Dfill': {
84+
this.ctx.save();
85+
this.ctx.fillStyle = o.fill || '';
86+
const p2d = new Path2D(drawing.path);
87+
this.ctx.fill(p2d);
88+
this.ctx.restore();
89+
break;
90+
}
91+
case 'path2Dpattern': {
92+
if (hasDocument) {
93+
const size = drawing.size;
94+
const hcanvas = document.createElement('canvas');
95+
const hcontext = hcanvas.getContext('2d');
96+
const bbox = this.computeBBox(drawing.path);
97+
if (bbox && (bbox.width || bbox.height)) {
98+
hcanvas.width = this.canvas.width;
99+
hcanvas.height = this.canvas.height;
100+
hcontext.translate(bbox.x || 0, bbox.y || 0);
101+
}
102+
else {
103+
hcanvas.width = size[0];
104+
hcanvas.height = size[1];
105+
}
106+
this.fillSketch(hcontext, drawing, o);
107+
this.ctx.save();
108+
this.ctx.fillStyle = this.ctx.createPattern(hcanvas, 'repeat');
109+
const p2d = new Path2D(drawing.path);
110+
this.ctx.fill(p2d);
111+
this.ctx.restore();
112+
}
113+
break;
114+
}
115+
}
116+
}
117+
}
118+
computeBBox(d) {
119+
if (hasDocument) {
120+
try {
121+
const ns = 'http://www.w3.org/2000/svg';
122+
const svg = document.createElementNS(ns, 'svg');
123+
svg.setAttribute('width', '0');
124+
svg.setAttribute('height', '0');
125+
const pathNode = self.document.createElementNS(ns, 'path');
126+
pathNode.setAttribute('d', d);
127+
svg.appendChild(pathNode);
128+
document.body.appendChild(svg);
129+
const bbox = pathNode.getBBox();
130+
document.body.removeChild(svg);
131+
return bbox;
132+
}
133+
catch (err) { }
134+
}
135+
return null;
136+
}
137+
fillSketch(ctx, drawing, o) {
138+
let fweight = o.fillWeight;
139+
if (fweight < 0) {
140+
fweight = o.strokeWidth / 2;
141+
}
142+
ctx.save();
143+
ctx.strokeStyle = o.fill || '';
144+
ctx.lineWidth = fweight;
145+
this._drawToContext(ctx, drawing);
146+
ctx.restore();
147+
}
148+
_drawToContext(ctx, drawing) {
149+
ctx.beginPath();
150+
for (const item of drawing.ops) {
151+
const data = item.data;
152+
switch (item.op) {
153+
case 'move':
154+
ctx.moveTo(data[0], data[1]);
155+
break;
156+
case 'bcurveTo':
157+
ctx.bezierCurveTo(data[0], data[1], data[2], data[3], data[4], data[5]);
158+
break;
159+
case 'qcurveTo':
160+
ctx.quadraticCurveTo(data[0], data[1], data[2], data[3]);
161+
break;
162+
case 'lineTo':
163+
ctx.lineTo(data[0], data[1]);
164+
break;
165+
}
166+
}
167+
if (drawing.type === 'fillPath') {
168+
ctx.fill();
169+
}
170+
else {
171+
ctx.stroke();
172+
}
173+
}
174+
}

bin/common/core.d.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export interface Options {
2+
maxRandomnessOffset: number;
3+
roughness: number;
4+
bowing: number;
5+
stroke: string;
6+
strokeWidth: number;
7+
curveTightness: number;
8+
curveStepCount: number;
9+
fill: string | null;
10+
fillStyle: string;
11+
fillWeight: number;
12+
hachureAngle: number;
13+
hachureGap: number;
14+
}
15+
export declare type OpType = 'move' | 'bcurveTo' | 'lineTo';
16+
export declare type OpSetType = 'path' | 'fillPath' | 'fillSketch';
17+
export interface Op {
18+
op: OpType;
19+
data: number[];
20+
}
21+
export interface OpSet {
22+
type: OpSetType;
23+
ops: Op[];
24+
}
25+
export interface Drawable {
26+
shape: string;
27+
options: Options;
28+
sets: OpSet[];
29+
}

bin/common/core.js

Whitespace-only changes.

bin/common/geometry.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export declare type Point = [number, number];
2+
export interface Rectangle {
3+
x: number;
4+
y: number;
5+
width: number;
6+
height: number;
7+
}

bin/common/geometry.js

Whitespace-only changes.

0 commit comments

Comments
 (0)