未验证 提交 938faec4 编写于 作者: P Preet 提交者: GitHub

Merge pull request #83 from pshihn/optional-options

Optional options
......@@ -10,6 +10,21 @@ export interface DrawingSurface {
height: number | SVGAnimatedLength;
}
export interface Options {
maxRandomnessOffset?: number;
roughness?: number;
bowing?: number;
stroke?: string;
strokeWidth?: number;
curveTightness?: number;
curveStepCount?: number;
fill?: string;
fillStyle?: string;
fillWeight?: number;
hachureAngle?: number;
hachureGap?: number;
simplification?: number;
}
export interface ResolvedOptions extends Options {
maxRandomnessOffset: number;
roughness: number;
bowing: number;
......@@ -17,12 +32,10 @@ export interface Options {
strokeWidth: number;
curveTightness: number;
curveStepCount: number;
fill: string | null;
fillStyle: string;
fillWeight: number;
hachureAngle: number;
hachureGap: number;
simplification?: number;
}
export declare type OpType = 'move' | 'bcurveTo' | 'lineTo' | 'qcurveTo';
export declare type OpSetType = 'path' | 'fillPath' | 'fillSketch' | 'path2Dfill' | 'path2Dpattern';
......@@ -38,7 +51,7 @@ export interface OpSet {
}
export interface Drawable {
shape: string;
options: Options;
options: ResolvedOptions;
sets: OpSet[];
}
export interface PathInfo {
......
import { PatternFiller, RenderHelper } from './filler-interface';
import { Options, OpSet } from '../core';
import { ResolvedOptions, OpSet } from '../core';
import { Point } from '../geometry';
export declare class DotFiller implements PatternFiller {
renderer: RenderHelper;
constructor(renderer: RenderHelper);
fillPolygon(points: Point[], o: Options): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet;
fillPolygon(points: Point[], o: ResolvedOptions): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet;
private dotsOnLines;
}
import { Options, OpSet, Op } from '../core';
import { ResolvedOptions, OpSet, Op } from '../core';
import { Point } from '../geometry';
export interface PatternFiller {
fillPolygon(points: Point[], o: Options): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet;
fillPolygon(points: Point[], o: ResolvedOptions): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet;
}
export interface RenderHelper {
doubleLine(x1: number, y1: number, x2: number, y2: number, o: Options): Op[];
getOffset(min: number, max: number, ops: Options): number;
ellipse(x: number, y: number, width: number, height: number, o: Options): OpSet;
doubleLine(x1: number, y1: number, x2: number, y2: number, o: ResolvedOptions): Op[];
getOffset(min: number, max: number, ops: ResolvedOptions): number;
ellipse(x: number, y: number, width: number, height: number, o: ResolvedOptions): OpSet;
}
import { Point, Line } from '../geometry';
import { Options } from '../core';
import { ResolvedOptions } from '../core';
import { RenderHelper } from './filler-interface';
export declare function lineLength(line: Line): number;
export declare function getIntersectingLines(line: number[], points: Point[]): Point[];
export declare function affine(x: number, y: number, cx: number, cy: number, sinAnglePrime: number, cosAnglePrime: number, R: number): Point;
export declare function hachureLinesForPolygon(points: Point[], o: Options): Line[];
export declare function hachureLinesForEllipse(cx: number, cy: number, width: number, height: number, o: Options, renderer: RenderHelper): Line[];
export declare function hachureLinesForPolygon(points: Point[], o: ResolvedOptions): Line[];
export declare function hachureLinesForEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions, renderer: RenderHelper): Line[];
import { Options } from '../core';
import { ResolvedOptions } from '../core';
import { PatternFiller, RenderHelper } from './filler-interface';
export declare function getFiller(renderer: RenderHelper, o: Options): PatternFiller;
export declare function getFiller(renderer: RenderHelper, o: ResolvedOptions): PatternFiller;
import { PatternFiller, RenderHelper } from './filler-interface';
import { Options, OpSet } from '../core';
import { ResolvedOptions, OpSet } from '../core';
import { Point } from '../geometry';
export declare class HachureFiller implements PatternFiller {
renderer: RenderHelper;
constructor(renderer: RenderHelper);
fillPolygon(points: Point[], o: Options): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet;
protected _fillPolygon(points: Point[], o: Options, connectEnds?: boolean): OpSet;
protected _fillEllipse(cx: number, cy: number, width: number, height: number, o: Options, connectEnds?: boolean): OpSet;
fillPolygon(points: Point[], o: ResolvedOptions): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet;
protected _fillPolygon(points: Point[], o: ResolvedOptions, connectEnds?: boolean): OpSet;
protected _fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions, connectEnds?: boolean): OpSet;
private renderLines;
}
import { HachureFiller } from './hachure-filler';
import { Options, OpSet } from '../core';
import { ResolvedOptions, OpSet } from '../core';
import { Point } from '../geometry';
export declare class HatchFiller extends HachureFiller {
fillPolygon(points: Point[], o: Options): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet;
fillPolygon(points: Point[], o: ResolvedOptions): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet;
}
import { HachureFiller } from './hachure-filler';
import { Options, OpSet } from '../core';
import { ResolvedOptions, OpSet } from '../core';
import { Point } from '../geometry';
export declare class ZigZagFiller extends HachureFiller {
fillPolygon(points: Point[], o: Options): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet;
fillPolygon(points: Point[], o: ResolvedOptions): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet;
}
import { RoughRenderer } from './renderer.js';
import { Config, DrawingSurface, Options, Drawable, OpSet, PathInfo } from './core';
import { Config, DrawingSurface, Options, ResolvedOptions, Drawable, OpSet, PathInfo } from './core';
import { Point } from './geometry.js';
export declare class RoughGenerator {
private config;
private surface;
private renderer;
defaultOptions: Options;
defaultOptions: ResolvedOptions;
constructor(config: Config | null, surface: DrawingSurface);
protected _options(options?: Options): Options;
protected _drawable(shape: string, sets: OpSet[], options: Options): Drawable;
protected _options(options?: Options): ResolvedOptions;
protected _drawable(shape: string, sets: OpSet[], options: ResolvedOptions): Drawable;
protected readonly lib: RoughRenderer;
private getCanvasSize;
protected computePolygonSize(points: Point[]): Point;
......
......@@ -10,7 +10,6 @@ export class RoughGenerator {
strokeWidth: 1,
curveTightness: 0,
curveStepCount: 9,
fill: null,
fillStyle: 'hachure',
fillWeight: -1,
hachureAngle: -41,
......
import { Options, OpSet, Op } from './core';
import { ResolvedOptions, OpSet, Op } from './core';
import { Point } from './geometry';
export declare class RoughRenderer {
line(x1: number, y1: number, x2: number, y2: number, o: Options): OpSet;
linearPath(points: Point[], close: boolean, o: Options): OpSet;
polygon(points: Point[], o: Options): OpSet;
rectangle(x: number, y: number, width: number, height: number, o: Options): OpSet;
curve(points: Point[], o: Options): OpSet;
ellipse(x: number, y: number, width: number, height: number, o: Options): OpSet;
arc(x: number, y: number, width: number, height: number, start: number, stop: number, closed: boolean, roughClosure: boolean, o: Options): OpSet;
svgPath(path: string, o: Options): OpSet;
solidFillPolygon(points: Point[], o: Options): OpSet;
patternFillPolygon(points: Point[], o: Options): OpSet;
patternFillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet;
patternFillArc(x: number, y: number, width: number, height: number, start: number, stop: number, o: Options): OpSet;
getOffset(min: number, max: number, ops: Options): number;
doubleLine(x1: number, y1: number, x2: number, y2: number, o: Options): Op[];
line(x1: number, y1: number, x2: number, y2: number, o: ResolvedOptions): OpSet;
linearPath(points: Point[], close: boolean, o: ResolvedOptions): OpSet;
polygon(points: Point[], o: ResolvedOptions): OpSet;
rectangle(x: number, y: number, width: number, height: number, o: ResolvedOptions): OpSet;
curve(points: Point[], o: ResolvedOptions): OpSet;
ellipse(x: number, y: number, width: number, height: number, o: ResolvedOptions): OpSet;
arc(x: number, y: number, width: number, height: number, start: number, stop: number, closed: boolean, roughClosure: boolean, o: ResolvedOptions): OpSet;
svgPath(path: string, o: ResolvedOptions): OpSet;
solidFillPolygon(points: Point[], o: ResolvedOptions): OpSet;
patternFillPolygon(points: Point[], o: ResolvedOptions): OpSet;
patternFillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet;
patternFillArc(x: number, y: number, width: number, height: number, start: number, stop: number, o: ResolvedOptions): OpSet;
getOffset(min: number, max: number, ops: ResolvedOptions): number;
doubleLine(x1: number, y1: number, x2: number, y2: number, o: ResolvedOptions): Op[];
private _line;
private _curve;
private _ellipse;
......
......@@ -85,7 +85,7 @@ export class RoughSVG {
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'fillSketch': {
......@@ -97,7 +97,7 @@ export class RoughSVG {
path.setAttribute('d', drawing.path || '');
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'path2Dpattern': {
......@@ -144,7 +144,7 @@ export class RoughSVG {
}
const path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = o.fill;
path.style.stroke = o.fill || null;
path.style.strokeWidth = fweight + '';
path.style.fill = 'none';
return path;
......
......@@ -1717,7 +1717,6 @@ var rough = (function () {
strokeWidth: 1,
curveTightness: 0,
curveStepCount: 9,
fill: null,
fillStyle: 'hachure',
fillWeight: -1,
hachureAngle: -41,
......@@ -2704,7 +2703,7 @@ var rough = (function () {
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'fillSketch':
......@@ -2718,7 +2717,7 @@ var rough = (function () {
path.setAttribute('d', drawing.path || '');
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'path2Dpattern':
......@@ -2784,7 +2783,7 @@ var rough = (function () {
}
var path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = o.fill;
path.style.stroke = o.fill || null;
path.style.strokeWidth = fweight + '';
path.style.fill = 'none';
return path;
......
此差异已折叠。
......@@ -1462,7 +1462,6 @@ var rough = (function () {
strokeWidth: 1,
curveTightness: 0,
curveStepCount: 9,
fill: null,
fillStyle: 'hachure',
fillWeight: -1,
hachureAngle: -41,
......@@ -2218,7 +2217,7 @@ var rough = (function () {
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'fillSketch': {
......@@ -2230,7 +2229,7 @@ var rough = (function () {
path.setAttribute('d', drawing.path || '');
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'path2Dpattern': {
......@@ -2277,7 +2276,7 @@ var rough = (function () {
}
const path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = o.fill;
path.style.stroke = o.fill || null;
path.style.strokeWidth = fweight + '';
path.style.fill = 'none';
return path;
......
此差异已折叠。
......@@ -1720,7 +1720,6 @@
strokeWidth: 1,
curveTightness: 0,
curveStepCount: 9,
fill: null,
fillStyle: 'hachure',
fillWeight: -1,
hachureAngle: -41,
......@@ -2707,7 +2706,7 @@
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'fillSketch':
......@@ -2721,7 +2720,7 @@
path.setAttribute('d', drawing.path || '');
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'path2Dpattern':
......@@ -2787,7 +2786,7 @@
}
var path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = o.fill;
path.style.stroke = o.fill || null;
path.style.strokeWidth = fweight + '';
path.style.fill = 'none';
return path;
......
此差异已折叠。
......@@ -1465,7 +1465,6 @@
strokeWidth: 1,
curveTightness: 0,
curveStepCount: 9,
fill: null,
fillStyle: 'hachure',
fillWeight: -1,
hachureAngle: -41,
......@@ -2221,7 +2220,7 @@
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'fillSketch': {
......@@ -2233,7 +2232,7 @@
path.setAttribute('d', drawing.path || '');
path.style.stroke = 'none';
path.style.strokeWidth = '0';
path.style.fill = o.fill;
path.style.fill = o.fill || null;
break;
}
case 'path2Dpattern': {
......@@ -2280,7 +2279,7 @@
}
const path = doc.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', this.opsToPath(drawing));
path.style.stroke = o.fill;
path.style.stroke = o.fill || null;
path.style.strokeWidth = fweight + '';
path.style.fill = 'none';
return path;
......
此差异已折叠。
{
"name": "roughjs",
"version": "2.2.3",
"version": "2.2.4",
"description": "Create graphics using HTML Canvas or SVG with a hand-drawn, sketchy, appearance.",
"main": "dist/rough.umd.js",
"module": "bin/rough.js",
......
import { Config, Options, Drawable, OpSet } from './core';
import { Config, Options, ResolvedOptions, Drawable, OpSet } from './core';
import { RoughGenerator } from './generator';
import { RoughRenderer } from './renderer';
import { Point } from './geometry';
......@@ -157,7 +157,7 @@ export class RoughCanvas {
return null;
}
private fillSketch(ctx: CanvasRenderingContext2D, drawing: OpSet, o: Options) {
private fillSketch(ctx: CanvasRenderingContext2D, drawing: OpSet, o: ResolvedOptions) {
let fweight = o.fillWeight;
if (fweight < 0) {
fweight = o.strokeWidth / 2;
......
......@@ -13,6 +13,22 @@ export interface DrawingSurface {
}
export interface Options {
maxRandomnessOffset?: number;
roughness?: number;
bowing?: number;
stroke?: string;
strokeWidth?: number;
curveTightness?: number;
curveStepCount?: number;
fill?: string;
fillStyle?: string;
fillWeight?: number;
hachureAngle?: number;
hachureGap?: number;
simplification?: number;
}
export interface ResolvedOptions extends Options {
maxRandomnessOffset: number;
roughness: number;
bowing: number;
......@@ -20,12 +36,10 @@ export interface Options {
strokeWidth: number;
curveTightness: number;
curveStepCount: number;
fill: string | null;
fillStyle: string;
fillWeight: number;
hachureAngle: number;
hachureGap: number;
simplification?: number;
}
export declare type OpType = 'move' | 'bcurveTo' | 'lineTo' | 'qcurveTo';
......@@ -45,7 +59,7 @@ export interface OpSet {
export interface Drawable {
shape: string;
options: Options;
options: ResolvedOptions;
sets: OpSet[];
}
......
import { PatternFiller, RenderHelper } from './filler-interface';
import { Options, OpSet, Op } from '../core';
import { ResolvedOptions, OpSet, Op } from '../core';
import { Point, Line } from '../geometry';
import { hachureLinesForPolygon, hachureLinesForEllipse, lineLength } from './filler-utils';
......@@ -10,19 +10,19 @@ export class DotFiller implements PatternFiller {
this.renderer = renderer;
}
fillPolygon(points: Point[], o: Options): OpSet {
fillPolygon(points: Point[], o: ResolvedOptions): OpSet {
o = Object.assign({}, o, { curveStepCount: 4, hachureAngle: 0 });
const lines = hachureLinesForPolygon(points, o);
return this.dotsOnLines(lines, o);
}
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet {
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet {
o = Object.assign({}, o, { curveStepCount: 4, hachureAngle: 0 });
const lines = hachureLinesForEllipse(cx, cy, width, height, o, this.renderer);
return this.dotsOnLines(lines, o);
}
private dotsOnLines(lines: Line[], o: Options): OpSet {
private dotsOnLines(lines: Line[], o: ResolvedOptions): OpSet {
let ops: Op[] = [];
let gap = o.hachureGap;
if (gap < 0) {
......
import { Options, OpSet, Op } from '../core';
import { ResolvedOptions, OpSet, Op } from '../core';
import { Point } from '../geometry';
export interface PatternFiller {
fillPolygon(points: Point[], o: Options): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet;
fillPolygon(points: Point[], o: ResolvedOptions): OpSet;
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet;
}
export interface RenderHelper {
doubleLine(x1: number, y1: number, x2: number, y2: number, o: Options): Op[];
getOffset(min: number, max: number, ops: Options): number;
ellipse(x: number, y: number, width: number, height: number, o: Options): OpSet;
doubleLine(x1: number, y1: number, x2: number, y2: number, o: ResolvedOptions): Op[];
getOffset(min: number, max: number, ops: ResolvedOptions): number;
ellipse(x: number, y: number, width: number, height: number, o: ResolvedOptions): OpSet;
}
\ No newline at end of file
import { Point, Segment, Line } from '../geometry';
import { Options } from '../core';
import { ResolvedOptions } from '../core';
import { HachureIterator } from '../utils/hachure';
import { RenderHelper } from './filler-interface';
......@@ -34,7 +34,7 @@ export function affine(x: number, y: number, cx: number, cy: number, sinAnglePri
];
}
export function hachureLinesForPolygon(points: Point[], o: Options): Line[] {
export function hachureLinesForPolygon(points: Point[], o: ResolvedOptions): Line[] {
const ret: Line[] = [];
if (points && points.length) {
let left = points[0][0];
......@@ -74,7 +74,7 @@ export function hachureLinesForPolygon(points: Point[], o: Options): Line[] {
return ret;
}
export function hachureLinesForEllipse(cx: number, cy: number, width: number, height: number, o: Options, renderer: RenderHelper): Line[] {
export function hachureLinesForEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions, renderer: RenderHelper): Line[] {
const ret: Line[] = [];
let rx = Math.abs(width / 2);
let ry = Math.abs(height / 2);
......
import { Options } from '../core';
import { ResolvedOptions } from '../core';
import { PatternFiller, RenderHelper } from './filler-interface';
import { HachureFiller } from './hachure-filler';
import { ZigZagFiller } from './zigzag-filler';
......@@ -7,7 +7,7 @@ import { DotFiller } from './dot-filler';
const fillers: { [name: string]: PatternFiller } = {};
export function getFiller(renderer: RenderHelper, o: Options): PatternFiller {
export function getFiller(renderer: RenderHelper, o: ResolvedOptions): PatternFiller {
let fillerName = o.fillStyle || 'hachure';
if (!fillers[fillerName]) {
switch (fillerName) {
......
import { PatternFiller, RenderHelper } from './filler-interface';
import { Options, OpSet, Op } from '../core';
import { ResolvedOptions, OpSet, Op } from '../core';
import { Point, Line } from '../geometry';
import { hachureLinesForPolygon, hachureLinesForEllipse } from './filler-utils';
......@@ -10,27 +10,27 @@ export class HachureFiller implements PatternFiller {
this.renderer = renderer;
}
fillPolygon(points: Point[], o: Options): OpSet {
fillPolygon(points: Point[], o: ResolvedOptions): OpSet {
return this._fillPolygon(points, o);
}
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet {
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet {
return this._fillEllipse(cx, cy, width, height, o);
}
protected _fillPolygon(points: Point[], o: Options, connectEnds: boolean = false): OpSet {
protected _fillPolygon(points: Point[], o: ResolvedOptions, connectEnds: boolean = false): OpSet {
const lines = hachureLinesForPolygon(points, o);
const ops = this.renderLines(lines, o, connectEnds);
return { type: 'fillSketch', ops };
}
protected _fillEllipse(cx: number, cy: number, width: number, height: number, o: Options, connectEnds: boolean = false): OpSet {
protected _fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions, connectEnds: boolean = false): OpSet {
const lines = hachureLinesForEllipse(cx, cy, width, height, o, this.renderer);
const ops = this.renderLines(lines, o, connectEnds);
return { type: 'fillSketch', ops };
}
private renderLines(lines: Line[], o: Options, connectEnds: boolean): Op[] {
private renderLines(lines: Line[], o: ResolvedOptions, connectEnds: boolean): Op[] {
let ops: Op[] = [];
let prevPoint: Point | null = null;
for (const line of lines) {
......
import { HachureFiller } from './hachure-filler';
import { Options, OpSet } from '../core';
import { ResolvedOptions, OpSet } from '../core';
import { Point } from '../geometry';
export class HatchFiller extends HachureFiller {
fillPolygon(points: Point[], o: Options): OpSet {
fillPolygon(points: Point[], o: ResolvedOptions): OpSet {
const set = this._fillPolygon(points, o);
const o2 = Object.assign({}, o, { hachureAngle: o.hachureAngle + 90 });
const set2 = this._fillPolygon(points, o2);
......@@ -11,7 +11,7 @@ export class HatchFiller extends HachureFiller {
return set;
}
fillEllipse(cx: number, cy: number, width: number, height: number, o: Options): OpSet {
fillEllipse(cx: number, cy: number, width: number, height: number, o: ResolvedOptions): OpSet {
const set = this._fillEllipse(cx, cy, width, height, o);
const o2 = Object.assign({}, o, { hachureAngle: <