Skip to content

Commit

Permalink
Refactoring renderer code. In progress.
Browse files Browse the repository at this point in the history
  • Loading branch information
Perlkonig committed Feb 9, 2019
1 parent d3c10b9 commit a061bc0
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 20 deletions.
79 changes: 67 additions & 12 deletions src/renderer.ts → src/RendererBase.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,91 @@
// import svg, { Nested } from "@svgdotjs/svg.js";
import svg from "svg.js";
import { GridPoints } from "./GridGenerator";
import { rectOfSquares } from "./grids";
import { APRenderRep } from "./schema";
import { sheets } from "./sheets";

export class Renderer {
export interface IRendererOptions {
sheetList?: string[];
colours?: string[];
patterns?: boolean;
patternList?: string[];
colourBlind?: boolean;
}

export abstract class RendererBase {
public readonly name: string;
public readonly coloursBasic = ["#e41a1c", "#377eb8", "#4daf4a", "#ffff33", "#984ea3", "#ff7f00", "#a65628", "#f781bf", "#999999"];
public readonly coloursBlind = ["#a6611a", "#80cdc1", "#018571", "#dfc27d"];
public readonly patternsBW = ["microbial", "chevrons", "honeycomb", "triangles", "wavy", "slant", "dots", "starsWhite", "cross", "houndstooth"];
public readonly patternNames = ["microbial", "chevrons", "honeycomb", "triangles", "wavy", "slant", "dots", "starsWhite", "cross", "houndstooth"];

constructor(name = "default") {
this.name = name;
}

public render(json: APRenderRep, draw: svg.Doc, sheetList: string[]): void {
json = this.prechecks(json);
public abstract render(json: APRenderRep, draw: svg.Doc, opts: IRendererOptions): void;

// Board first
const board = draw.group().id("board");
board.circle(100).fill("#999").stroke({width: 2, color: "black"});
}

protected prechecks(json: APRenderRep): APRenderRep {
protected jsonPrechecks(json: APRenderRep): APRenderRep {
// Check for missing renderer
if ("renderer" ! in json) {
if (json.renderer === undefined) {
json.renderer = "default";
}

// Make sure the JSON is intended for you
if (json.renderer !== this.name) {
throw Error(`Renderer mismatch. The JSON data you provided is intended for the "${json.renderer}" renderer, but the "${this.name}" renderer received it.`);
throw new Error(`Renderer mismatch. The JSON data you provided is intended for the "${json.renderer}" renderer, but the "${this.name}" renderer received it.`);
}

return json;
}

protected optionsPrecheck(opts: IRendererOptions): IRendererOptions {
const newOpts: IRendererOptions = {sheetList: ["default"], colourBlind: false};

// Check colour blindness
if (opts.colourBlind !== undefined) {
newOpts.colourBlind = opts.colourBlind;
}

// Validate sheet list
if ( (opts.sheetList !== undefined) && (opts.sheetList.length > 0) ) {
for (const name of opts.sheetList) {
if (! sheets.has(name)) {
throw new Error(`A glyph sheet you requested could not be found: ${ name }`);
}
}
newOpts.sheetList = opts.sheetList;
}

// Validate patterns settings
newOpts.patterns = false;
if (opts.patterns) {
newOpts.patterns = true;
// Validate pattern list if given
if ( (opts.patternList !== undefined) && (opts.patternList.length > 0) ) {
for (const name of opts.patternList) {
if (this.patternNames.indexOf(name) < 0) {
throw new Error(`A pattern you requested could not be found: ${ name }`);
}
}
newOpts.patternList = opts.patternList;
}
}

// Validate colour list if given
if ( (opts.colours !== undefined) && (opts.colours.length > 0) ) {
const re = new RegExp(/^\#[a-f0-9]{6}$/, "i");
for (const c of opts.colours) {
if (! re.test(c)) {
throw new Error(`One of the colours you requested is malformed: ${ c }`);
}
}
newOpts.colours = opts.colours;
}

return newOpts;
}

protected loadPatterns(canvas: svg.Doc): void {
// Keep in alphabetical order.
// If you change any `id`s, you need to change them in the `patternsBW` property, too.
Expand All @@ -59,4 +110,8 @@ export class Renderer {

canvas.defs().svg("<pattern id='wavy' patternUnits='userSpaceOnUse' width='15' height='20' viewbox='0 0 75 100'><svg xmlns='http://www.w3.org/2000/svg' width='75' height='100'><rect width='75' height='100' fill='#fff'/><circle cx='75' cy='50' r='28.3%' stroke-width='12' stroke='#000' fill='none'/><circle cx='0' r='28.3%' stroke-width='12' stroke='#000' fill='none'/><circle cy='100' r='28.3%' stroke-width='12' stroke='#000' fill='none'/></svg></pattern>");
}

protected getGlyph(glyph: string, canvas: svg.Container) {
// Do stuff
}
}
53 changes: 51 additions & 2 deletions src/renderers/default.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,52 @@
import { Renderer } from "../renderer";
import svg from "svg.js";
import { rectOfSquares } from "../grids";
import { IRendererOptions, RendererBase } from "../RendererBase";
import { APRenderRep } from "../schema";

export const DefaultRenderer = new Renderer();
export class DefaultRenderer extends RendererBase {

public render(json: APRenderRep, draw: svg.Doc, opts: IRendererOptions): void {
json = this.jsonPrechecks(json);
opts = this.optionsPrecheck(opts);

// If patterns were requested, load them into the canvas
if (opts.patterns) {
this.loadPatterns(draw);
}

// Delegate to style-specific renderer
if (! ("style" in json.board)) {
throw new Error(`This 'board' schema cannot be handled by the '${ this.name }' renderer.`);
}
switch (json.board.style) {
case "squares-checkered": {
this.squaresCheckered(json, draw, opts);
break;
}
default: {
throw new Error(`The requested board style (${ json.board.style })is not yet supported by the default renderer.`);
break;
}
}
}

private squaresCheckered(json: APRenderRep, draw: svg.Doc, opts: IRendererOptions): void {
// Check required properites
if ( (! ("width" in json.board)) || (! ("height" in json.board)) || (json.board.width === undefined) || (json.board.height === undefined) ) {
throw new Error("Both the `width` and `height` properties are required for this board type.");
}
const width: number = json.board.width;
const height: number = json.board.height;

// Get a grid of points
const grid = rectOfSquares({gridHeight: json.board.height, gridWidth: json.board.width});

// Determine whether the first row starts with a light or dark square
let startLight: number = 1;
if (height % 2 === 0) {
startLight = 0;
}

const board = draw.group().id("board");
}
}
8 changes: 5 additions & 3 deletions src/renderers/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Renderer } from "../renderer";
import { RendererBase } from "../RendererBase";
import { DefaultRenderer } from "./default";

const renderers = new Map<string, Renderer>();
renderers.set(DefaultRenderer.name, DefaultRenderer);
export { RendererBase as Renderer, DefaultRenderer };

const renderers = new Map<string, RendererBase>();
renderers.set(DefaultRenderer.name, new DefaultRenderer());
export {renderers};
4 changes: 2 additions & 2 deletions src/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@
"$ref": "#/definitions/positiveInteger"
},
"width": {
"description": "Optional. If not provided, the renderer will calculate based on the `pieces` property. If only one of 'width' and 'height' is specifed, the board is assumed to be square.",
"description": "Required for the `squares*`, `vertex`, and `go` styles.",
"$ref": "#/definitions/positiveInteger"
},
"height": {
"description": "Optional. If not provided, the renderer will calculate based on the `pieces` property. If only one of 'width' and 'height' is specifed, the board is assumed to be square.",
"description": "Required for the `squares*`, `vertex`, and `go` styles.",
"$ref": "#/definitions/positiveInteger"
},
"tiling": {
Expand Down
3 changes: 2 additions & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
],
"jsRules": {},
"rules": {
"max-line-length": false
"max-line-length": false,
"array-type": false
},
"rulesDirectory": []
}

0 comments on commit a061bc0

Please sign in to comment.