diff --git a/.gitignore b/.gitignore index e9a7ac29..8fe76adc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,4 @@ -/font-renderer/target -/partitioner/target -/path-utils/target -/utils/frontend/target /utils/gamma-lut/target -/demo/client/target -/demo/client/*.html -/demo/client/*.js -/demo/client/src/*.js -/demo/client/src/*.js.map -/demo/client/node_modules -/demo/client/package-lock.json -/demo/server/target -/demo/server/Rocket.toml -/demo2/dist .DS_Store target node_modules diff --git a/demo2/cover.fs.glsl b/demo2/cover.fs.glsl deleted file mode 100644 index e2c851bc..00000000 --- a/demo2/cover.fs.glsl +++ /dev/null @@ -1,26 +0,0 @@ -#version 300 es - -// pathfinder/demo2/cover.fs.glsl -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -precision highp float; - -uniform sampler2D uStencilTexture; - -in vec2 vTexCoord; -in float vBackdrop; -in vec4 vColor; - -out vec4 oFragColor; - -void main() { - float coverage = abs(texture(uStencilTexture, vTexCoord).r + vBackdrop); - oFragColor = vec4(vColor.rgb, vColor.a * coverage); -} diff --git a/demo2/cover.vs.glsl b/demo2/cover.vs.glsl deleted file mode 100644 index d77c5932..00000000 --- a/demo2/cover.vs.glsl +++ /dev/null @@ -1,45 +0,0 @@ -#version 300 es - -// pathfinder/demo2/cover.vs.glsl -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -precision highp float; - -uniform vec2 uFramebufferSize; -uniform vec2 uTileSize; -uniform vec2 uStencilTextureSize; -uniform sampler2D uFillColorsTexture; -uniform vec2 uFillColorsTextureSize; -uniform vec2 uViewBoxOrigin; - -in vec2 aTessCoord; -in vec2 aTileOrigin; -in int aBackdrop; -in uint aObject; - -out vec2 vTexCoord; -out float vBackdrop; -out vec4 vColor; - -vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { - uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); - uvec2 tileOffset = uvec2(tileIndex % tilesPerRow, tileIndex / tilesPerRow); - return vec2(tileOffset) * uTileSize; -} - -void main() { - uint tileIndex = uint(gl_InstanceID); - vec2 position = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; - vec2 texCoord = computeTileOffset(tileIndex, uStencilTextureSize.x) + aTessCoord * uTileSize; - vTexCoord = texCoord / uStencilTextureSize; - vBackdrop = float(aBackdrop); - vColor = texture(uFillColorsTexture, vec2(float(aObject) / uFillColorsTextureSize.x, 0.0)); - gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0); -} diff --git a/demo2/declaration.d.ts b/demo2/declaration.d.ts deleted file mode 100644 index 4a93eef5..00000000 --- a/demo2/declaration.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module "*.glsl"; -declare module "*.jpg"; -declare module "*.png"; -declare module "*.svg"; - -declare function require(s: string): any; diff --git a/demo2/geometry.ts b/demo2/geometry.ts deleted file mode 100644 index 6edfb601..00000000 --- a/demo2/geometry.ts +++ /dev/null @@ -1,151 +0,0 @@ -// pathfinder/demo2/geometry.ts -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -export const EPSILON: number = 1e-6; - -export class Point2D { - x: number; - y: number; - - constructor(x: number, y: number) { - this.x = x; - this.y = y; - Object.freeze(this); - } - - approxEq(other: Point2D, epsilon: number | undefined): boolean { - return approxEq(this.x, other.x, epsilon) && approxEq(this.y, other.y, epsilon); - } - - lerp(other: Point2D, t: number): Point2D { - return new Point2D(lerp(this.x, other.x, t), lerp(this.y, other.y, t)); - } - - translate(x: number, y: number): Point2D { - return new Point2D(this.x + x, this.y + y); - } - - add(other: Point2D): Point2D { - return new Point2D(this.x + other.x, this.y + other.y); - } - - sub(other: Point2D): Point2D { - return new Point2D(this.x - other.x, this.y - other.y); - } - - normalize(): Point2D { - const length = this.length(); - return new Point2D(this.x / length, this.y / length); - } - - length(): number { - return Math.sqrt(this.x * this.x + this.y * this.y); - } - - scale(factor: number): Point2D { - return new Point2D(this.x * factor, this.y * factor); - } -} - -export class Size2D { - width: number; - height: number; - - constructor(width: number, height: number) { - this.width = width; - this.height = height; - Object.freeze(this); - } -} - -export class Rect { - origin: Point2D; - size: Size2D; - - constructor(origin: Point2D, size: Size2D) { - this.origin = origin; - this.size = size; - Object.freeze(this); - } - - unionWithPoint(point: Point2D): Rect { - let newOrigin = this.origin, newSize = this.size; - - if (point.x < this.origin.x) { - newSize = { - width: newSize.width + newOrigin.x - point.x, - height: newSize.height, - }; - newOrigin = new Point2D(point.x, newOrigin.y); - } else if (point.x > this.maxX()) { - newSize = { - width: newSize.width + point.x - this.maxX(), - height: newSize.height, - }; - } - - if (point.y < this.origin.y) { - newSize = { - width: newSize.width, - height: newSize.height + newOrigin.y - point.y, - }; - newOrigin = new Point2D(newOrigin.x, point.y); - } else if (point.y > this.maxY()) { - newSize = { - width: newSize.width, - height: newSize.height + point.y - this.maxY(), - }; - } - - return new Rect(newOrigin, newSize); - } - - maxX(): number { - return this.origin.x + this.size.width; - } - - maxY(): number { - return this.origin.y + this.size.height; - } -} - -export interface Vector3D { - x: number; - y: number; - z: number; -} - -export class Matrix2D { - a: number; b: number; - c: number; d: number; - tx: number; ty: number; - - constructor(a: number, b: number, c: number, d: number, tx: number, ty: number) { - this.a = a; this.b = b; - this.c = c; this.d = d; - this.tx = tx; this.ty = ty; - } -} - -export function approxEq(a: number, b: number, epsilon: number | undefined): boolean { - return Math.abs(a - b) <= (epsilon == null ? EPSILON : epsilon); -} - -export function lerp(a: number, b: number, t: number): number { - return a + (b - a) * t; -} - -export function cross(a: Vector3D, b: Vector3D): Vector3D { - return { - x: a.y*b.z - a.z*b.y, - y: a.z*b.x - a.x*b.z, - z: a.x*b.y - a.y*b.x, - }; -} diff --git a/demo2/index.html b/demo2/index.html deleted file mode 100644 index 78fa63d6..00000000 --- a/demo2/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - Pathfinder Demo - - - - - - - - - diff --git a/demo2/opaque.fs.glsl b/demo2/opaque.fs.glsl deleted file mode 100644 index fe579b29..00000000 --- a/demo2/opaque.fs.glsl +++ /dev/null @@ -1,21 +0,0 @@ -#version 300 es - -// pathfinder/demo2/opaque.fs.glsl -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -precision highp float; - -in vec4 vColor; - -out vec4 oFragColor; - -void main() { - oFragColor = vColor; -} diff --git a/demo2/opaque.vs.glsl b/demo2/opaque.vs.glsl deleted file mode 100644 index 5f9ba286..00000000 --- a/demo2/opaque.vs.glsl +++ /dev/null @@ -1,31 +0,0 @@ -#version 300 es - -// pathfinder/demo2/opaque.vs.glsl -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -precision highp float; - -uniform vec2 uFramebufferSize; -uniform vec2 uTileSize; -uniform sampler2D uFillColorsTexture; -uniform vec2 uFillColorsTextureSize; -uniform vec2 uViewBoxOrigin; - -in vec2 aTessCoord; -in vec2 aTileOrigin; -in uint aObject; - -out vec4 vColor; - -void main() { - vec2 position = (aTileOrigin + aTessCoord) * uTileSize + uViewBoxOrigin; - vColor = texture(uFillColorsTexture, vec2(float(aObject) / uFillColorsTextureSize.x, 0.0)); - gl_Position = vec4((position / uFramebufferSize * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0); -} diff --git a/demo2/package-lock.json b/demo2/package-lock.json deleted file mode 100644 index 641d2bf7..00000000 --- a/demo2/package-lock.json +++ /dev/null @@ -1,2165 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@choojs/findup": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@choojs/findup/-/findup-0.2.1.tgz", - "integrity": "sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw==", - "dev": true, - "requires": { - "commander": "^2.15.1" - } - }, - "@types/bezier-js": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/bezier-js/-/bezier-js-0.0.6.tgz", - "integrity": "sha1-DZdtaBY8SVUzLveYohoLPWOB0Ss=" - }, - "@types/node": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-7.10.2.tgz", - "integrity": "sha512-RO4ig5taKmcrU4Rex8ojG1gpwFkjddzug9iPQSDvbewHN9vDpcFewevkaOK+KT+w1LeZnxbgOyfXwV4pxsQ4GQ==" - }, - "@types/opentype.js": { - "version": "0.0.0", - "resolved": "http://registry.npmjs.org/@types/opentype.js/-/opentype.js-0.0.0.tgz", - "integrity": "sha1-AvZD18Y8Pr9PZG/GBa5Gg/hJrxs=" - }, - "@types/pdfkit": { - "version": "0.7.36", - "resolved": "https://registry.npmjs.org/@types/pdfkit/-/pdfkit-0.7.36.tgz", - "integrity": "sha512-9eRA6MuW+n78yU3HhoIrDxjyAX2++B5MpLDYqHOnaRTquCw+5sYXT+QN8E1eSaxvNUwlRfU3tOm4UzTeGWmBqg==", - "requires": { - "@types/node": "*" - } - }, - "@types/webgl2": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/@types/webgl2/-/webgl2-0.0.4.tgz", - "integrity": "sha512-PACt1xdErJbMUOUweSrbVM7gSIYm1vTncW2hF6Os/EeWi6TXYAYMPp+8v6rzHmypE5gHrxaxZNXgMkJVIdZpHw==" - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "bezier-js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-2.3.1.tgz", - "integrity": "sha512-nFpFL9tuayvlHfWh6xM7OHeTZvwr74+6KnzO3eNZMt0BC0cqb9lCTc9C8OVzrHBvbrNwriTw7XaF2SBsWQJLZA==" - }, - "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", - "dev": true - }, - "bootstrap": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.1.3.tgz", - "integrity": "sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==" - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", - "integrity": "sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=" - }, - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "events": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/events/-/events-1.1.1.tgz", - "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "^2.1.0" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glsl-inject-defines": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/glsl-inject-defines/-/glsl-inject-defines-1.0.3.tgz", - "integrity": "sha1-3RqswsF/yyvT/DJBHGYz0Ne2D9Q=", - "dev": true, - "requires": { - "glsl-token-inject-block": "^1.0.0", - "glsl-token-string": "^1.0.1", - "glsl-tokenizer": "^2.0.2" - } - }, - "glsl-resolve": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/glsl-resolve/-/glsl-resolve-0.0.1.tgz", - "integrity": "sha1-iUvvc5ENeSyBtRQxgANdCnivdtM=", - "dev": true, - "requires": { - "resolve": "^0.6.1", - "xtend": "^2.1.2" - }, - "dependencies": { - "resolve": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz", - "integrity": "sha1-3ZV5gufnNt699TtYpN2RdUV13UY=", - "dev": true - } - } - }, - "glsl-token-assignments": { - "version": "2.0.2", - "resolved": "http://registry.npmjs.org/glsl-token-assignments/-/glsl-token-assignments-2.0.2.tgz", - "integrity": "sha1-pdgqt4SZwuimuDy2lJXm5mXOAZ8=", - "dev": true - }, - "glsl-token-defines": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/glsl-token-defines/-/glsl-token-defines-1.0.0.tgz", - "integrity": "sha1-y4kqqVmTYjFyhHDU90AySJaX+p0=", - "dev": true, - "requires": { - "glsl-tokenizer": "^2.0.0" - } - }, - "glsl-token-depth": { - "version": "1.1.2", - "resolved": "http://registry.npmjs.org/glsl-token-depth/-/glsl-token-depth-1.1.2.tgz", - "integrity": "sha1-I8XjDuK9JViEtKKLyFC495HpXYQ=", - "dev": true - }, - "glsl-token-descope": { - "version": "1.0.2", - "resolved": "http://registry.npmjs.org/glsl-token-descope/-/glsl-token-descope-1.0.2.tgz", - "integrity": "sha1-D8kKsyYYa4L1l7LnfcniHvzTIHY=", - "dev": true, - "requires": { - "glsl-token-assignments": "^2.0.0", - "glsl-token-depth": "^1.1.0", - "glsl-token-properties": "^1.0.0", - "glsl-token-scope": "^1.1.0" - } - }, - "glsl-token-inject-block": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/glsl-token-inject-block/-/glsl-token-inject-block-1.1.0.tgz", - "integrity": "sha1-4QFfWYDBCRgkraomJfHf3ovQADQ=", - "dev": true - }, - "glsl-token-properties": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/glsl-token-properties/-/glsl-token-properties-1.0.1.tgz", - "integrity": "sha1-SD3D2Dnw1LXGFx0VkfJJvlPCip4=", - "dev": true - }, - "glsl-token-scope": { - "version": "1.1.2", - "resolved": "http://registry.npmjs.org/glsl-token-scope/-/glsl-token-scope-1.1.2.tgz", - "integrity": "sha1-oXKOeN8kRE+cuT/RjvD3VQOmQ7E=", - "dev": true - }, - "glsl-token-string": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/glsl-token-string/-/glsl-token-string-1.0.1.tgz", - "integrity": "sha1-WUQdL4V958NEnJRWZgIezjWOSOw=", - "dev": true - }, - "glsl-token-whitespace-trim": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/glsl-token-whitespace-trim/-/glsl-token-whitespace-trim-1.0.0.tgz", - "integrity": "sha1-RtHf6Yx1vX1QTAXX0RsbPpzJOxA=", - "dev": true - }, - "glsl-tokenizer": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/glsl-tokenizer/-/glsl-tokenizer-2.1.5.tgz", - "integrity": "sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==", - "dev": true, - "requires": { - "through2": "^0.6.3" - } - }, - "glslify-bundle": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-5.1.1.tgz", - "integrity": "sha512-plaAOQPv62M1r3OsWf2UbjN0hUYAB7Aph5bfH58VxJZJhloRNbxOL9tl/7H71K7OLJoSJ2ZqWOKk3ttQ6wy24A==", - "dev": true, - "requires": { - "glsl-inject-defines": "^1.0.1", - "glsl-token-defines": "^1.0.0", - "glsl-token-depth": "^1.1.1", - "glsl-token-descope": "^1.0.2", - "glsl-token-scope": "^1.1.1", - "glsl-token-string": "^1.0.1", - "glsl-token-whitespace-trim": "^1.0.0", - "glsl-tokenizer": "^2.0.2", - "murmurhash-js": "^1.0.0", - "shallow-copy": "0.0.1" - } - }, - "glslify-deps": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/glslify-deps/-/glslify-deps-1.3.1.tgz", - "integrity": "sha512-Ogm179MCazwIRyEqs3g3EOY4Y3XIAa0yl8J5RE9rJC6QH1w8weVOp2RZu0mvnYy/2xIas1w166YR2eZdDkWQxg==", - "dev": true, - "requires": { - "@choojs/findup": "^0.2.0", - "events": "^1.0.2", - "glsl-resolve": "0.0.1", - "glsl-tokenizer": "^2.0.0", - "graceful-fs": "^4.1.2", - "inherits": "^2.0.1", - "map-limit": "0.0.1", - "resolve": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true - }, - "graham_scan": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/graham_scan/-/graham_scan-1.0.4.tgz", - "integrity": "sha1-OZZR3R+DU+GID1nqjl+Uud9Mkoo=" - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "http://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "http://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "makerjs": { - "version": "0.9.93", - "resolved": "https://registry.npmjs.org/makerjs/-/makerjs-0.9.93.tgz", - "integrity": "sha512-XztS2tJEpL01dsZ5P11kGO2MitrD6MsSvkNDS3uUDVN9SVDJn33Q2j9DFruJsiRtqNVRseLK52vkkbWKtLB/tA==", - "requires": { - "@types/bezier-js": "^0.0.6", - "@types/node": "^7.0.5", - "@types/opentype.js": "^0.0.0", - "@types/pdfkit": "^0.7.34", - "bezier-js": "^2.1.0", - "clone": "^1.0.2", - "graham_scan": "^1.0.4" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-limit": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz", - "integrity": "sha1-63lhAxwPDo0AG/LVb6toXViCLzg=", - "dev": true, - "requires": { - "once": "~1.3.0" - } - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "murmurhash-js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz", - "integrity": "sha1-sGJ44h/Gw3+lMTcysEEry2rhX1E=", - "dev": true - }, - "nan": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.0.tgz", - "integrity": "sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "parse-color": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-color/-/parse-color-1.0.0.tgz", - "integrity": "sha1-e3SLlag/A/FqlPU15S1/PZRlhhk=", - "requires": { - "color-convert": "~0.5.0" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "sass": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.15.2.tgz", - "integrity": "sha512-YFncPpx3ewKEhMg9sWdCxKUpPN/jwVLa0Q9iO2tcV5Y5Z/YAlFV6k6JaQwq3tmbN6FXKjUYElXRHcG0g4D1zkQ==", - "dev": true, - "requires": { - "chokidar": "^2.0.0" - } - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "shallow-copy": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz", - "integrity": "sha1-QV9CcC1z2BAzApLMXuhurhoRoXA=", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "svg-path-outline": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/svg-path-outline/-/svg-path-outline-1.0.1.tgz", - "integrity": "sha1-w5Zk922IdGW4voXER3jIg0Jomas=", - "requires": { - "makerjs": "^0.9.39" - } - }, - "svgpath": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/svgpath/-/svgpath-2.2.1.tgz", - "integrity": "sha1-CDS7Z8iadkcrK9BswQH6e1F7Iiw=" - }, - "through2": { - "version": "0.6.5", - "resolved": "http://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - }, - "dependencies": { - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "typescript": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.1.6.tgz", - "integrity": "sha512-tDMYfVtvpb96msS1lDX9MEdHrW4yOuZ4Kdc4Him9oU796XldPYF/t2+uKoX0BBa0hXXwDlqYQbXY5Rzjzc5hBA==", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-2.2.0.tgz", - "integrity": "sha1-7vax8ZjByN6vrYsXZaBNrUoBxak=", - "dev": true - } - } -} diff --git a/demo2/package.json b/demo2/package.json deleted file mode 100644 index 429ec9c8..00000000 --- a/demo2/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "devDependencies": { - "glslify-bundle": "^5.1.1", - "glslify-deps": "^1.3.1", - "sass": "^1.15.2", - "typescript": "^3.1.6" - }, - "dependencies": { - "@types/webgl2": "0.0.4", - "bootstrap": "^4.1.3", - "parse-color": "^1.0.0", - "svg-path-outline": "^1.0.1", - "svgpath": "^2.2.1" - } -} diff --git a/demo2/path-utils.ts b/demo2/path-utils.ts deleted file mode 100644 index a59fea02..00000000 --- a/demo2/path-utils.ts +++ /dev/null @@ -1,301 +0,0 @@ -// pathfinder/demo2/path-utils.ts -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -import {Point2D, Rect, EPSILON} from "./geometry"; -import {SVGPath, Edge} from "./tiling"; -import { ENGINE_METHOD_DIGESTS } from "constants"; -import { AssertionError } from "assert"; -import { unwrapNull, unwrapUndef } from "./util"; - -const SVGPath: (path: string) => SVGPath = require('svgpath'); - -export class PathSegment { - command: string; - points: Point2D[]; - - constructor(segment: string[]) { - const points = []; - for (let i = 1; i < segment.length; i += 2) - points.push(new Point2D(parseFloat(segment[i]), parseFloat(segment[i + 1]))); - this.points = points; - this.command = segment[0]; - } - - to(): Point2D | null { - return this.points[this.points.length - 1]; - } - - toStringPieces(): string[] { - const pieces = [this.command]; - for (const point of this.points) { - pieces.push(" " + point.x); - pieces.push(" " + point.y); - } - return pieces; - } - - toString(): string { - return this.toStringPieces().join(" "); - } -} - -export function flattenPath(path: SVGPath): SVGPath { - let lastPoint: Point2D | null = null; - return path.unshort().abs().iterate(segmentPieces => { - let segment = new PathSegment(segmentPieces); - if (segment.command === 'C' && lastPoint != null) { - const cubicEdge = new CubicEdge(lastPoint, - segment.points[0], - segment.points[1], - segment.points[2]); - //console.log("cubic edge", cubicEdge); - const edges: Edge[] = cubicEdge.toQuadraticEdges(); - /*const edges: Edge[] = [ - new Edge(lastPoint, - segment.points[0].lerp(segment.points[1], 0.5), - segment.points[2]), - ];*/ - const newSegments = edges.map(edge => edge.toSVGPieces()); - //console.log("... resulting new segments:", newSegments); - lastPoint = segment.to(); - return newSegments; - } - if (segment.command === 'H' && lastPoint != null) - segment = new PathSegment(['L', segmentPieces[1], "" + lastPoint.y]); - if (segment.command === 'V' && lastPoint != null) - segment = new PathSegment(['L', "" + lastPoint.x, segmentPieces[1]]); - lastPoint = segment.to(); - return [segment.toStringPieces()]; - }); -} - -export function makePathMonotonic(path: SVGPath): SVGPath { - let lastPoint: Point2D | null = null; - return path.iterate(segmentPieces => { - let segment = new PathSegment(segmentPieces); - if (segment.command === 'Q' && lastPoint != null) { - const edge = new Edge(lastPoint, segment.points[0], segment.points[1]); - const minX = Math.min(edge.from.x, edge.to.x); - const maxX = Math.max(edge.from.x, edge.to.x); - - const edgesX: Edge[] = []; - if (edge.ctrl!.x < minX || edge.ctrl!.x > maxX) { - const t = (edge.from.x - edge.ctrl!.x) / - (edge.from.x - 2.0 * edge.ctrl!.x + edge.to.x); - const subdivided = edge.subdivideAt(t); - if (t < -EPSILON || t > 1.0 + EPSILON) - throw new Error("Bad t value when making monotonic X!"); - edgesX.push(subdivided.prev, subdivided.next); - } else { - edgesX.push(edge); - } - - const newEdges = []; - for (const edge of edgesX) { - const minY = Math.min(edge.from.y, edge.to.y); - const maxY = Math.max(edge.from.y, edge.to.y); - - if (edge.ctrl!.y < minY || edge.ctrl!.y > maxY) { - const t = (edge.from.y - edge.ctrl!.y) / - (edge.from.y - 2.0 * edge.ctrl!.y + edge.to.y); - if (t < -EPSILON || t > 1.0 + EPSILON) - throw new Error("Bad t value when making monotonic Y!"); - const subdivided = edge.subdivideAt(t); - newEdges.push(subdivided.prev, subdivided.next); - } else { - newEdges.push(edge); - } - } - - lastPoint = segment.to(); - return newEdges.map(newEdge => newEdge.toSVGPieces()); - } - - lastPoint = segment.to(); - return [segment.toStringPieces()]; - }); -} - -export class Outline { - suboutlines: Suboutline[]; - - constructor(path: SVGPath) { - this.suboutlines = []; - let suboutline = new Suboutline; - path.iterate(segmentPieces => { - const segment = new PathSegment(segmentPieces); - if (segment.command === 'M') { - if (!suboutline.isEmpty()) { - this.suboutlines.push(suboutline); - suboutline = new Suboutline; - } - } - for (let pointIndex = 0; pointIndex < segment.points.length; pointIndex++) { - suboutline.points.push(new OutlinePoint(segment.points[pointIndex], - pointIndex < segment.points.length - 1)); - } - }); - if (!suboutline.isEmpty()) - this.suboutlines.push(suboutline); - } - - calculateNormals(): void { - for (const suboutline of this.suboutlines) - suboutline.calculateNormals(); - } - - stroke(radius: number): void { - for (const suboutline of this.suboutlines) - suboutline.stroke(radius); - } - - toSVGPathString(): string { - return this.suboutlines.map(suboutline => suboutline.toSVGPathString()).join(" "); - } -} - -export class Suboutline { - points: OutlinePoint[]; - normals: Point2D[] | null; - - constructor() { - this.points = []; - this.normals = null; - } - - isEmpty(): boolean { - return this.points.length === 0; - } - - calculateNormals(): void { - this.normals = []; - for (let pointIndex = 0; pointIndex < this.points.length; pointIndex++) { - const prevPointIndex = pointIndex === 0 ? this.points.length - 1 : pointIndex - 1; - const nextPointIndex = pointIndex === this.points.length - 1 ? 0 : pointIndex + 1; - const prevPoint = this.points[prevPointIndex].position; - const point = this.points[pointIndex].position; - const nextPoint = this.points[nextPointIndex].position; - let prevVector = prevPoint.sub(point), nextVector = nextPoint.sub(point); - this.normals.push(prevVector.add(nextVector).normalize()); - } - } - - stroke(radius: number): void { - if (this.normals == null) - throw new Error("Calculate normals first!"); - const newPoints = []; - for (let pointIndex = 0; pointIndex < this.points.length; pointIndex++) { - const point = this.points[pointIndex], normal = this.normals[pointIndex]; - const newPosition = point.position.sub(normal.scale(radius)); - newPoints.push(new OutlinePoint(newPosition, point.offCurve)); - } - for (let pointIndex = this.points.length - 1; pointIndex >= 0; pointIndex--) { - const point = this.points[pointIndex], normal = this.normals[pointIndex]; - const newPosition = point.position.add(normal.scale(radius)); - newPoints.push(new OutlinePoint(newPosition, point.offCurve)); - } - this.points = newPoints; - this.normals = null; - } - - toSVGPathString(): string { - let string = ""; - const queuedPositions = []; - for (let pointIndex = 0; pointIndex < this.points.length; pointIndex++) { - const point = this.points[pointIndex]; - queuedPositions.push(point.position); - if (pointIndex > 0 && point.offCurve) - continue; - let command: string; - if (pointIndex === 0) - command = 'M'; - else if (queuedPositions.length === 1) - command = 'L'; - else - command = 'Q'; - string += command + " "; - for (const position of queuedPositions) - string += position.x + " " + position.y + " "; - queuedPositions.splice(0); - } - string += "Z"; - return string; - } -} - -export class OutlinePoint { - position: Point2D; - offCurve: boolean; - - constructor(position: Point2D, offCurve: boolean) { - this.position = position; - this.offCurve = offCurve; - } -} - -class CubicEdge { - from: Point2D; - ctrl0: Point2D; - ctrl1: Point2D; - to: Point2D; - - constructor(from: Point2D, ctrl0: Point2D, ctrl1: Point2D, to: Point2D) { - this.from = from; - this.ctrl0 = ctrl0; - this.ctrl1 = ctrl1; - this.to = to; - } - - subdivideAt(t: number): SubdividedCubicEdges { - const p0 = this.from, p1 = this.ctrl0, p2 = this.ctrl1, p3 = this.to; - const p01 = p0.lerp(p1, t), p12 = p1.lerp(p2, t), p23 = p2.lerp(p3, t); - const p012 = p01.lerp(p12, t), p123 = p12.lerp(p23, t); - const p0123 = p012.lerp(p123, t); - return { - prev: new CubicEdge(p0, p01, p012, p0123), - next: new CubicEdge(p0123, p123, p23, p3), - }; - } - - toQuadraticEdges(): Edge[] { - const MAX_APPROXIMATION_ITERATIONS: number = 32; - const TOLERANCE: number = 0.1; - - const results = [], worklist: CubicEdge[] = [this]; - while (worklist.length > 0) { - let current = unwrapUndef(worklist.pop()); - for (let iteration = 0; iteration < MAX_APPROXIMATION_ITERATIONS; iteration++) { - const deltaCtrl0 = current.from.sub(current.ctrl0.scale(3.0)) - .add(current.ctrl1.scale(3.0).sub(current.to)); - const deltaCtrl1 = current.ctrl0.scale(3.0) - .sub(current.from) - .add(current.to.sub(current.ctrl1.scale(3.0))); - const maxError = Math.max(deltaCtrl0.length(), deltaCtrl1.length()) / 6.0; - if (maxError < TOLERANCE) - break; - - const subdivided = current.subdivideAt(0.5); - worklist.push(subdivided.next); - current = subdivided.prev; - } - - const approxCtrl0 = current.ctrl0.scale(3.0).sub(current.from).scale(0.5); - const approxCtrl1 = current.ctrl1.scale(3.0).sub(current.to).scale(0.5); - results.push(new Edge(current.from, approxCtrl0.lerp(approxCtrl1, 0.5), current.to)); - } - - return results; - } -} - -interface SubdividedCubicEdges { - prev: CubicEdge; - next: CubicEdge; -} diff --git a/demo2/pathfinder.scss b/demo2/pathfinder.scss deleted file mode 100644 index db8f3a61..00000000 --- a/demo2/pathfinder.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import "./node_modules/bootstrap/scss/bootstrap.scss"; - -html, body { - height: 100%; - width: 100%; -} - -#open-wrapper { - display: block; - position: absolute; - right: 0; - bottom: 0; -} diff --git a/demo2/pathfinder.ts b/demo2/pathfinder.ts deleted file mode 100644 index e141c517..00000000 --- a/demo2/pathfinder.ts +++ /dev/null @@ -1,734 +0,0 @@ -// pathfinder/demo2/pathfinder.ts -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -import COVER_VERTEX_SHADER_SOURCE from "./cover.vs.glsl"; -import COVER_FRAGMENT_SHADER_SOURCE from "./cover.fs.glsl"; -import OPAQUE_VERTEX_SHADER_SOURCE from "./opaque.vs.glsl"; -import OPAQUE_FRAGMENT_SHADER_SOURCE from "./opaque.fs.glsl"; -import STENCIL_VERTEX_SHADER_SOURCE from "./stencil.vs.glsl"; -import STENCIL_FRAGMENT_SHADER_SOURCE from "./stencil.fs.glsl"; -import AREA_LUT from "../resources/textures/area-lut.png"; -import {Matrix2D, Size2D, Rect, Point2D} from "./geometry"; -import {SVGPath, TILE_SIZE} from "./tiling"; -import {staticCast, unwrapNull} from "./util"; - -const SVGPath: (path: string) => SVGPath = require('svgpath'); - -const STENCIL_FRAMEBUFFER_SIZE: Size2D = { - width: TILE_SIZE.width * 256, - height: TILE_SIZE.height * 256, -}; - -const QUAD_VERTEX_POSITIONS: Uint8Array = new Uint8Array([ - 0, 0, - 1, 0, - 1, 1, - 0, 1, -]); - -const FILL_INSTANCE_SIZE: number = 8; -const SOLID_TILE_INSTANCE_SIZE: number = 6; -const MASK_TILE_INSTANCE_SIZE: number = 8; - -interface Color { - r: number; - g: number; - b: number; - a: number; -} - -type Edge = 'left' | 'top' | 'right' | 'bottom'; - -type FillProgram = - Program<'FramebufferSize' | 'TileSize' | 'AreaLUT', - 'TessCoord' | 'FromPx' | 'ToPx' | 'FromSubpx' | 'ToSubpx' | 'TileIndex'>; -type SolidTileProgram = - Program<'FramebufferSize' | - 'TileSize' | - 'FillColorsTexture' | 'FillColorsTextureSize' | - 'ViewBoxOrigin', - 'TessCoord' | 'TileOrigin' | 'Object'>; -type MaskTileProgram = - Program<'FramebufferSize' | - 'TileSize' | - 'StencilTexture' | 'StencilTextureSize' | - 'FillColorsTexture' | 'FillColorsTextureSize' | - 'ViewBoxOrigin', - 'TessCoord' | 'TileOrigin' | 'Backdrop' | 'Object'>; - -class App { - private canvas: HTMLCanvasElement; - private openButton: HTMLInputElement; - private areaLUT: HTMLImageElement; - - private gl: WebGL2RenderingContext; - private disjointTimerQueryExt: any; - private areaLUTTexture: WebGLTexture; - private fillColorsTexture: WebGLTexture; - private stencilTexture: WebGLTexture; - private stencilFramebuffer: WebGLFramebuffer; - private fillProgram: FillProgram; - private solidTileProgram: SolidTileProgram; - private maskTileProgram: MaskTileProgram; - private quadVertexBuffer: WebGLBuffer; - private solidTileVertexBuffer: WebGLBuffer; - private solidVertexArray: WebGLVertexArrayObject; - private batchBuffers: BatchBuffers[]; - - private viewBox: Rect; - - private solidTileCount: number; - private shaderCount: number; - - constructor(areaLUT: HTMLImageElement) { - const canvas = staticCast(document.getElementById('canvas'), HTMLCanvasElement); - const openButton = staticCast(document.getElementById('open'), HTMLInputElement); - this.canvas = canvas; - this.openButton = openButton; - this.areaLUT = areaLUT; - - this.openButton.addEventListener('change', event => this.loadFile(), false); - - const devicePixelRatio = window.devicePixelRatio; - canvas.width = window.innerWidth * devicePixelRatio; - canvas.height = window.innerHeight * devicePixelRatio; - canvas.style.width = window.innerWidth + "px"; - canvas.style.height = window.innerHeight + "px"; - - const gl = unwrapNull(this.canvas.getContext('webgl2', {antialias: false})); - this.gl = gl; - gl.getExtension('EXT_color_buffer_float'); - this.disjointTimerQueryExt = gl.getExtension('EXT_disjoint_timer_query'); - - this.areaLUTTexture = unwrapNull(gl.createTexture()); - gl.bindTexture(gl.TEXTURE_2D, this.areaLUTTexture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, areaLUT); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.fillColorsTexture = unwrapNull(gl.createTexture()); - - /* - const benchData = new Uint8Array(1600 * 1600 * 4); - for (let i = 0; i < benchData.length; i++) - benchData[i] = (Math.random() * 256) | 0; - const benchTexture = unwrapNull(gl.createTexture()); - gl.bindTexture(gl.TEXTURE_2D, benchTexture); - const startTime = performance.now(); - for (let i = 0; i < 100; i++) - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1600, 1600, 0, gl.RGBA, gl.UNSIGNED_BYTE, benchData); - const elapsedTime = (performance.now() - startTime) / 100; - console.log("texture upload: ", elapsedTime, "ms"); - */ - - this.stencilTexture = unwrapNull(gl.createTexture()); - gl.bindTexture(gl.TEXTURE_2D, this.stencilTexture); - gl.texImage2D(gl.TEXTURE_2D, - 0, - gl.R16F, - STENCIL_FRAMEBUFFER_SIZE.width, - STENCIL_FRAMEBUFFER_SIZE.height, - 0, - gl.RED, - gl.HALF_FLOAT, - null); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - - this.stencilFramebuffer = unwrapNull(gl.createFramebuffer()); - gl.bindFramebuffer(gl.FRAMEBUFFER, this.stencilFramebuffer); - gl.framebufferTexture2D(gl.FRAMEBUFFER, - gl.COLOR_ATTACHMENT0, - gl.TEXTURE_2D, - this.stencilTexture, - 0); - if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) - throw new Error("Stencil framebuffer incomplete!"); - - const maskTileProgram = new Program(gl, - COVER_VERTEX_SHADER_SOURCE, - COVER_FRAGMENT_SHADER_SOURCE, - [ - 'FramebufferSize', - 'TileSize', - 'StencilTexture', - 'StencilTextureSize', - 'FillColorsTexture', - 'FillColorsTextureSize', - 'ViewBoxOrigin', - ], - [ - 'TessCoord', - 'TileOrigin', - 'TileIndex', - 'Backdrop', - 'Object', - ]); - this.maskTileProgram = maskTileProgram; - - const solidTileProgram = new Program(gl, - OPAQUE_VERTEX_SHADER_SOURCE, - OPAQUE_FRAGMENT_SHADER_SOURCE, - [ - 'FramebufferSize', - 'TileSize', - 'FillColorsTexture', - 'FillColorsTextureSize', - 'ViewBoxOrigin', - ], - ['TessCoord', 'TileOrigin', 'Object']); - this.solidTileProgram = solidTileProgram; - - const fillProgram = new Program(gl, - STENCIL_VERTEX_SHADER_SOURCE, - STENCIL_FRAGMENT_SHADER_SOURCE, - ['FramebufferSize', 'TileSize', 'AreaLUT'], - [ - 'TessCoord', - 'FromPx', 'ToPx', - 'FromSubpx', 'ToSubpx', - 'TileIndex' - ]); - this.fillProgram = fillProgram; - - // Initialize quad VBO. - this.quadVertexBuffer = unwrapNull(gl.createBuffer()); - gl.bindBuffer(gl.ARRAY_BUFFER, this.quadVertexBuffer); - gl.bufferData(gl.ARRAY_BUFFER, QUAD_VERTEX_POSITIONS, gl.STATIC_DRAW); - - // Initialize tile VBOs and IBOs. - this.solidTileVertexBuffer = unwrapNull(gl.createBuffer()); - - // Initialize solid tile VAO. - this.solidVertexArray = unwrapNull(gl.createVertexArray()); - gl.bindVertexArray(this.solidVertexArray); - gl.useProgram(this.solidTileProgram.program); - gl.bindBuffer(gl.ARRAY_BUFFER, this.quadVertexBuffer); - gl.vertexAttribPointer(solidTileProgram.attributes.TessCoord, - 2, - gl.UNSIGNED_BYTE, - false, - 0, - 0); - gl.bindBuffer(gl.ARRAY_BUFFER, this.solidTileVertexBuffer); - gl.vertexAttribPointer(solidTileProgram.attributes.TileOrigin, - 2, - gl.SHORT, - false, - SOLID_TILE_INSTANCE_SIZE, - 0); - gl.vertexAttribDivisor(solidTileProgram.attributes.TileOrigin, 1); - gl.vertexAttribIPointer(solidTileProgram.attributes.Object, - 1, - gl.UNSIGNED_SHORT, - SOLID_TILE_INSTANCE_SIZE, - 4); - gl.vertexAttribDivisor(solidTileProgram.attributes.Object, 1); - gl.enableVertexAttribArray(solidTileProgram.attributes.TessCoord); - gl.enableVertexAttribArray(solidTileProgram.attributes.TileOrigin); - gl.enableVertexAttribArray(solidTileProgram.attributes.Object); - - this.batchBuffers = []; - - this.viewBox = new Rect(new Point2D(0.0, 0.0), new Size2D(0.0, 0.0)); - - // Set up event handlers. - this.canvas.addEventListener('click', event => this.onClick(event), false); - - this.solidTileCount = 0; - this.shaderCount = 0; - } - - redraw(): void { - const gl = this.gl, canvas = this.canvas; - - //console.log("viewBox", this.viewBox); - - // Initialize timers. - let fillTimerQuery = null, solidTimerQuery = null, maskTimerQuery = null; - if (this.disjointTimerQueryExt != null) { - fillTimerQuery = unwrapNull(gl.createQuery()); - solidTimerQuery = unwrapNull(gl.createQuery()); - maskTimerQuery = unwrapNull(gl.createQuery()); - } - - // Clear. - if (solidTimerQuery != null) - gl.beginQuery(this.disjointTimerQueryExt.TIME_ELAPSED_EXT, solidTimerQuery); - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - const framebufferSize = {width: canvas.width, height: canvas.height}; - gl.viewport(0, 0, framebufferSize.width, framebufferSize.height); - gl.clearColor(0.85, 0.85, 0.85, 1.0); - gl.clear(gl.COLOR_BUFFER_BIT); - - // Draw solid tiles. - gl.bindVertexArray(this.solidVertexArray); - gl.useProgram(this.solidTileProgram.program); - gl.uniform2f(this.solidTileProgram.uniforms.FramebufferSize, - framebufferSize.width, - framebufferSize.height); - gl.uniform2f(this.solidTileProgram.uniforms.TileSize, TILE_SIZE.width, TILE_SIZE.height); - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.fillColorsTexture); - gl.uniform1i(this.solidTileProgram.uniforms.FillColorsTexture, 0); - // FIXME(pcwalton): Maybe this should be an ivec2 or uvec2? - gl.uniform2f(this.solidTileProgram.uniforms.FillColorsTextureSize, - this.shaderCount, - 1.0); - gl.uniform2f(this.solidTileProgram.uniforms.ViewBoxOrigin, - this.viewBox.origin.x, - this.viewBox.origin.y); - gl.disable(gl.BLEND); - gl.drawArraysInstanced(gl.TRIANGLE_FAN, 0, 4, this.solidTileCount); - if (solidTimerQuery != null) - gl.endQuery(this.disjointTimerQueryExt.TIME_ELAPSED_EXT); - - // Draw batches. - if (fillTimerQuery != null) - gl.beginQuery(this.disjointTimerQueryExt.TIME_ELAPSED_EXT, fillTimerQuery); - for (const batch of this.batchBuffers) { - // Fill. - gl.bindFramebuffer(gl.FRAMEBUFFER, this.stencilFramebuffer); - gl.viewport(0, 0, STENCIL_FRAMEBUFFER_SIZE.width, STENCIL_FRAMEBUFFER_SIZE.height); - gl.clearColor(0.0, 0.0, 0.0, 0.0); - gl.clear(gl.COLOR_BUFFER_BIT); - - gl.bindVertexArray(batch.fillVertexArray); - gl.useProgram(this.fillProgram.program); - gl.uniform2f(this.fillProgram.uniforms.FramebufferSize, - STENCIL_FRAMEBUFFER_SIZE.width, - STENCIL_FRAMEBUFFER_SIZE.height); - gl.uniform2f(this.fillProgram.uniforms.TileSize, TILE_SIZE.width, TILE_SIZE.height); - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.areaLUTTexture); - gl.uniform1i(this.fillProgram.uniforms.AreaLUT, 0); - gl.blendEquation(gl.FUNC_ADD); - gl.blendFunc(gl.ONE, gl.ONE); - gl.enable(gl.BLEND); - gl.drawArraysInstanced(gl.TRIANGLE_FAN, 0, 4, unwrapNull(batch.fillPrimitiveCount)); - console.log("drawing ", batch.fillPrimitiveCount, " fills"); - gl.disable(gl.BLEND); - - // Read back stencil and dump it. - //this.dumpStencil(); - - // Draw masked tiles. - gl.bindFramebuffer(gl.FRAMEBUFFER, null); - gl.viewport(0, 0, framebufferSize.width, framebufferSize.height); - gl.bindVertexArray(batch.maskVertexArray); - gl.useProgram(this.maskTileProgram.program); - gl.uniform2f(this.maskTileProgram.uniforms.FramebufferSize, - framebufferSize.width, - framebufferSize.height); - gl.uniform2f(this.maskTileProgram.uniforms.TileSize, - TILE_SIZE.width, - TILE_SIZE.height); - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.stencilTexture); - gl.uniform1i(this.maskTileProgram.uniforms.StencilTexture, 0); - gl.uniform2f(this.maskTileProgram.uniforms.StencilTextureSize, - STENCIL_FRAMEBUFFER_SIZE.width, - STENCIL_FRAMEBUFFER_SIZE.height); - gl.activeTexture(gl.TEXTURE1); - gl.bindTexture(gl.TEXTURE_2D, this.fillColorsTexture); - gl.uniform1i(this.maskTileProgram.uniforms.FillColorsTexture, 1); - // FIXME(pcwalton): Maybe this should be an ivec2 or uvec2? - gl.uniform2f(this.maskTileProgram.uniforms.FillColorsTextureSize, - this.shaderCount, - 1.0); - gl.uniform2f(this.maskTileProgram.uniforms.ViewBoxOrigin, - this.viewBox.origin.x, - this.viewBox.origin.y); - gl.blendEquation(gl.FUNC_ADD); - gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE); - gl.enable(gl.BLEND); - gl.drawArraysInstanced(gl.TRIANGLE_FAN, 0, 4, batch.maskTileCount); - gl.disable(gl.BLEND); - } - if (fillTimerQuery != null) - gl.endQuery(this.disjointTimerQueryExt.TIME_ELAPSED_EXT); - - // End timer. - if (fillTimerQuery != null && solidTimerQuery != null) { - processQueries(gl, this.disjointTimerQueryExt, { - fill: fillTimerQuery, - solid: solidTimerQuery, - }); - } - } - - private dumpStencil(): void { - const gl = this.gl; - - const totalStencilFramebufferSize = STENCIL_FRAMEBUFFER_SIZE.width * - STENCIL_FRAMEBUFFER_SIZE.height * 4; - const stencilData = new Float32Array(totalStencilFramebufferSize); - gl.readPixels(0, 0, - STENCIL_FRAMEBUFFER_SIZE.width, STENCIL_FRAMEBUFFER_SIZE.height, - gl.RGBA, - gl.FLOAT, - stencilData); - const stencilDumpData = new Uint8ClampedArray(totalStencilFramebufferSize); - for (let i = 0; i < stencilData.length; i++) - stencilDumpData[i] = stencilData[i] * 255.0; - const stencilDumpCanvas = document.createElement('canvas'); - stencilDumpCanvas.width = STENCIL_FRAMEBUFFER_SIZE.width; - stencilDumpCanvas.height = STENCIL_FRAMEBUFFER_SIZE.height; - stencilDumpCanvas.style.width = - (STENCIL_FRAMEBUFFER_SIZE.width / window.devicePixelRatio) + "px"; - stencilDumpCanvas.style.height = - (STENCIL_FRAMEBUFFER_SIZE.height / window.devicePixelRatio) + "px"; - const stencilDumpCanvasContext = unwrapNull(stencilDumpCanvas.getContext('2d')); - const stencilDumpImageData = new ImageData(stencilDumpData, - STENCIL_FRAMEBUFFER_SIZE.width, - STENCIL_FRAMEBUFFER_SIZE.height); - stencilDumpCanvasContext.putImageData(stencilDumpImageData, 0, 0); - document.body.appendChild(stencilDumpCanvas); - //console.log(stencilData); - } - - private loadFile(): void { - console.log("loadFile"); - // TODO(pcwalton) - const file = unwrapNull(unwrapNull(this.openButton.files)[0]); - const reader = new FileReader; - reader.addEventListener('loadend', () => { - const gl = this.gl; - const arrayBuffer = staticCast(reader.result, ArrayBuffer); - const root = new RIFFChunk(new DataView(arrayBuffer)); - for (const subchunk of root.subchunks(4)) { - const self = this; - - const id = subchunk.stringID(); - if (id === 'head') { - const headerData = subchunk.contents(); - const version = headerData.getUint32(0, true); - if (version !== 0) - throw new Error("Unknown version!"); - // Ignore the batch count and fetch the view box. - this.viewBox = new Rect(new Point2D(headerData.getFloat32(8, true), - headerData.getFloat32(12, true)), - new Size2D(headerData.getFloat32(16, true), - headerData.getFloat32(20, true))); - continue; - } else if (id === 'soli') { - self.solidTileCount = uploadArrayBuffer(subchunk, - this.solidTileVertexBuffer, - SOLID_TILE_INSTANCE_SIZE); - } else if (id === 'shad') { - this.shaderCount = subchunk.length() / 4; - gl.activeTexture(gl.TEXTURE0); - gl.bindTexture(gl.TEXTURE_2D, this.fillColorsTexture); - const textureDataView = subchunk.contents(); - const textureData = new Uint8Array(textureDataView.buffer, - textureDataView.byteOffset, - textureDataView.byteLength); - gl.texImage2D(gl.TEXTURE_2D, - 0, - gl.RGBA, - this.shaderCount, - 1, - 0, - gl.RGBA, - gl.UNSIGNED_BYTE, - textureData); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); - } else if (id === 'batc') { - const batch = new BatchBuffers(this.gl, - this.fillProgram, - this.maskTileProgram, - this.quadVertexBuffer); - for (const subsubchunk of subchunk.subchunks()) { - const id = subsubchunk.stringID(); - console.log("id=", id); - if (id === 'fill') { - batch.fillPrimitiveCount = uploadArrayBuffer(subsubchunk, - batch.fillVertexBuffer, - FILL_INSTANCE_SIZE); - } else if (id === 'mask') { - batch.maskTileCount = uploadArrayBuffer(subsubchunk, - batch.maskTileVertexBuffer, - MASK_TILE_INSTANCE_SIZE); - } - } - - this.batchBuffers.push(batch); - } - - function uploadArrayBuffer(chunk: RIFFChunk, - buffer: WebGLBuffer, - instanceSize: number): - number { - gl.bindBuffer(gl.ARRAY_BUFFER, buffer); - gl.bufferData(gl.ARRAY_BUFFER, chunk.contents(), gl.DYNAMIC_DRAW); - return chunk.length() / instanceSize; - } - } - - this.redraw(); - }, false); - reader.readAsArrayBuffer(file); - } - - private onClick(event: MouseEvent): void { - this.redraw(); - } -} - -class BatchBuffers { - fillVertexBuffer: WebGLBuffer; - fillVertexArray: WebGLVertexArrayObject; - maskTileVertexBuffer: WebGLBuffer; - maskVertexArray: WebGLVertexArrayObject; - fillPrimitiveCount: number; - maskTileCount: number; - - constructor(gl: WebGL2RenderingContext, - fillProgram: FillProgram, - maskTileProgram: MaskTileProgram, - quadVertexBuffer: WebGLBuffer) { - // Initialize fill VBOs. - this.fillVertexBuffer = unwrapNull(gl.createBuffer()); - - // Initialize fill VAO. - this.fillVertexArray = unwrapNull(gl.createVertexArray()); - gl.bindVertexArray(this.fillVertexArray); - gl.useProgram(fillProgram.program); - gl.bindBuffer(gl.ARRAY_BUFFER, quadVertexBuffer); - gl.vertexAttribPointer(fillProgram.attributes.TessCoord, - 2, - gl.UNSIGNED_BYTE, - false, - 0, - 0); - gl.bindBuffer(gl.ARRAY_BUFFER, this.fillVertexBuffer); - gl.vertexAttribIPointer(fillProgram.attributes.FromPx, - 1, - gl.UNSIGNED_BYTE, - FILL_INSTANCE_SIZE, - 0); - gl.vertexAttribDivisor(fillProgram.attributes.FromPx, 1); - gl.vertexAttribIPointer(fillProgram.attributes.ToPx, - 1, - gl.UNSIGNED_BYTE, - FILL_INSTANCE_SIZE, - 1); - gl.vertexAttribDivisor(fillProgram.attributes.ToPx, 1); - gl.vertexAttribPointer(fillProgram.attributes.FromSubpx, - 2, - gl.UNSIGNED_BYTE, - true, - FILL_INSTANCE_SIZE, - 2); - gl.vertexAttribDivisor(fillProgram.attributes.FromSubpx, 1); - gl.vertexAttribPointer(fillProgram.attributes.ToSubpx, - 2, - gl.UNSIGNED_BYTE, - true, - FILL_INSTANCE_SIZE, - 4); - gl.vertexAttribDivisor(fillProgram.attributes.ToSubpx, 1); - gl.vertexAttribIPointer(fillProgram.attributes.TileIndex, - 1, - gl.UNSIGNED_SHORT, - FILL_INSTANCE_SIZE, - 6); - gl.vertexAttribDivisor(fillProgram.attributes.TileIndex, 1); - gl.enableVertexAttribArray(fillProgram.attributes.TessCoord); - gl.enableVertexAttribArray(fillProgram.attributes.FromPx); - gl.enableVertexAttribArray(fillProgram.attributes.ToPx); - gl.enableVertexAttribArray(fillProgram.attributes.FromSubpx); - gl.enableVertexAttribArray(fillProgram.attributes.ToSubpx); - gl.enableVertexAttribArray(fillProgram.attributes.TileIndex); - - // Initialize tile VBOs. - this.maskTileVertexBuffer = unwrapNull(gl.createBuffer()); - - // Initialize mask tile VAO. - this.maskVertexArray = unwrapNull(gl.createVertexArray()); - gl.bindVertexArray(this.maskVertexArray); - gl.useProgram(maskTileProgram.program); - gl.bindBuffer(gl.ARRAY_BUFFER, quadVertexBuffer); - gl.vertexAttribPointer(maskTileProgram.attributes.TessCoord, - 2, - gl.UNSIGNED_BYTE, - false, - 0, - 0); - gl.bindBuffer(gl.ARRAY_BUFFER, this.maskTileVertexBuffer); - gl.vertexAttribPointer(maskTileProgram.attributes.TileOrigin, - 2, - gl.SHORT, - false, - MASK_TILE_INSTANCE_SIZE, - 0); - gl.vertexAttribDivisor(maskTileProgram.attributes.TileOrigin, 1); - gl.vertexAttribIPointer(maskTileProgram.attributes.Backdrop, - 1, - gl.SHORT, - MASK_TILE_INSTANCE_SIZE, - 4); - gl.vertexAttribDivisor(maskTileProgram.attributes.Backdrop, 1); - gl.vertexAttribIPointer(maskTileProgram.attributes.Object, - 1, - gl.UNSIGNED_SHORT, - MASK_TILE_INSTANCE_SIZE, - 6); - gl.vertexAttribDivisor(maskTileProgram.attributes.Object, 1); - gl.enableVertexAttribArray(maskTileProgram.attributes.TessCoord); - gl.enableVertexAttribArray(maskTileProgram.attributes.TileOrigin); - gl.enableVertexAttribArray(maskTileProgram.attributes.Backdrop); - gl.enableVertexAttribArray(maskTileProgram.attributes.Object); - - this.fillPrimitiveCount = 0; - this.maskTileCount = 0; - } -} - -class Program { - program: WebGLProgram; - uniforms: {[key in U]: WebGLUniformLocation | null}; - attributes: {[key in A]: number}; - - private vertexShader: WebGLShader; - private fragmentShader: WebGLShader; - - constructor(gl: WebGL2RenderingContext, - vertexShaderSource: string, - fragmentShaderSource: string, - uniformNames: U[], - attributeNames: A[]) { - this.vertexShader = unwrapNull(gl.createShader(gl.VERTEX_SHADER)); - gl.shaderSource(this.vertexShader, vertexShaderSource); - gl.compileShader(this.vertexShader); - if (!gl.getShaderParameter(this.vertexShader, gl.COMPILE_STATUS)) { - console.error(gl.getShaderInfoLog(this.vertexShader)); - throw new Error("Vertex shader compilation failed!"); - } - - this.fragmentShader = unwrapNull(gl.createShader(gl.FRAGMENT_SHADER)); - gl.shaderSource(this.fragmentShader, fragmentShaderSource); - gl.compileShader(this.fragmentShader); - if (!gl.getShaderParameter(this.fragmentShader, gl.COMPILE_STATUS)) { - console.error(gl.getShaderInfoLog(this.fragmentShader)); - throw new Error("Fragment shader compilation failed!"); - } - - this.program = unwrapNull(gl.createProgram()); - gl.attachShader(this.program, this.vertexShader); - gl.attachShader(this.program, this.fragmentShader); - gl.linkProgram(this.program); - if (!gl.getProgramParameter(this.program, gl.LINK_STATUS)) { - console.error(gl.getProgramInfoLog(this.program)); - throw new Error("Program linking failed!"); - } - - const uniforms: {[key in U]?: WebGLUniformLocation | null} = {}; - for (const uniformName of uniformNames) - uniforms[uniformName] = gl.getUniformLocation(this.program, "u" + uniformName); - this.uniforms = uniforms as {[key in U]: WebGLUniformLocation | null}; - - const attributes: {[key in A]?: number} = {}; - for (const attributeName of attributeNames) { - attributes[attributeName] = unwrapNull(gl.getAttribLocation(this.program, - "a" + attributeName)); - } - this.attributes = attributes as {[key in A]: number}; - } -} - -class RIFFChunk { - private data: DataView; - - constructor(data: DataView) { - this.data = data; - } - - stringID(): string { - return String.fromCharCode(this.data.getUint8(0), - this.data.getUint8(1), - this.data.getUint8(2), - this.data.getUint8(3)); - } - - length(): number { - return this.data.getUint32(4, true); - } - - contents(): DataView { - return new DataView(this.data.buffer, this.data.byteOffset + 8, this.length()); - } - - subchunks(initialOffset?: number | undefined): RIFFChunk[] { - const subchunks = []; - const contents = this.contents(), length = this.length(); - let offset = initialOffset == null ? 0 : initialOffset; - while (offset < length) { - const subchunk = new RIFFChunk(new DataView(contents.buffer, - contents.byteOffset + offset, - length - offset)); - subchunks.push(subchunk); - offset += subchunk.length() + 8; - } - return subchunks; - } -} - -interface Queries { - fill: WebGLQuery; - solid: WebGLQuery; -}; - -function getQueryResult(gl: WebGL2RenderingContext, disjointTimerQueryExt: any, query: WebGLQuery): - Promise { - function go(resolve: (n: number) => void): void { - const queryResultAvailable = disjointTimerQueryExt.QUERY_RESULT_AVAILABLE_EXT; - const queryResult = disjointTimerQueryExt.QUERY_RESULT_EXT; - if (!disjointTimerQueryExt.getQueryObjectEXT(query, queryResultAvailable)) { - setTimeout(() => go(resolve), 10); - return; - } - resolve(disjointTimerQueryExt.getQueryObjectEXT(query, queryResult) / 1000000.0); - } - - return new Promise((resolve, reject) => go(resolve)); -} - -function processQueries(gl: WebGL2RenderingContext, disjointTimerQueryExt: any, queries: Queries): - void { - Promise.all([ - getQueryResult(gl, disjointTimerQueryExt, queries.fill), - getQueryResult(gl, disjointTimerQueryExt, queries.solid), - ]).then(results => { - const [fillResult, solidResult] = results; - console.log(fillResult, "ms fill/mask,", solidResult, "ms solid"); - }); -} - -function loadAreaLUT(): Promise { - return new Promise((resolve, reject) => {; - const image = new Image; - image.src = AREA_LUT; - image.addEventListener('load', event => resolve(image), false); - }); -} - -function main(): void { - loadAreaLUT().then(image => new App(image)); -} - -document.addEventListener('DOMContentLoaded', () => main(), false); diff --git a/demo2/stencil.fs.glsl b/demo2/stencil.fs.glsl deleted file mode 100644 index b1f39c8f..00000000 --- a/demo2/stencil.fs.glsl +++ /dev/null @@ -1,42 +0,0 @@ -#version 300 es - -// pathfinder/demo2/stencil.fs.glsl -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -precision highp float; - -uniform sampler2D uAreaLUT; - -in vec2 vFrom; -in vec2 vTo; - -out vec4 oFragColor; - -void main() { - // Unpack. - vec2 from = vFrom, to = vTo; - - // Determine winding, and sort into a consistent order so we only need to find one root below. - bool winding = from.x < to.x; - vec2 left = winding ? from : to, right = winding ? to : from; - - // Shoot a vertical ray toward the curve. - vec2 window = clamp(vec2(from.x, to.x), -0.5, 0.5); - float offset = mix(window.x, window.y, 0.5) - left.x; - float t = offset / (right.x - left.x); - - // Compute position and derivative to form a line approximation. - float y = mix(left.y, right.y, t); - float d = (right.y - left.y) / (right.x - left.x); - - // Look up area under that line, and scale horizontally to the window size. - float dX = window.x - window.y; - oFragColor = vec4(texture(uAreaLUT, vec2(y + 8.0, abs(d * dX)) / 16.0).r * dX); -} diff --git a/demo2/stencil.vs.glsl b/demo2/stencil.vs.glsl deleted file mode 100644 index e91cea4d..00000000 --- a/demo2/stencil.vs.glsl +++ /dev/null @@ -1,58 +0,0 @@ -#version 300 es - -// pathfinder/demo2/stencil.vs.glsl -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -precision highp float; - -uniform vec2 uFramebufferSize; -uniform vec2 uTileSize; - -in vec2 aTessCoord; -in uint aFromPx; -in uint aToPx; -in vec2 aFromSubpx; -in vec2 aToSubpx; -in uint aTileIndex; - -out vec2 vFrom; -out vec2 vTo; - -vec2 computeTileOffset(uint tileIndex, float stencilTextureWidth) { - uint tilesPerRow = uint(stencilTextureWidth / uTileSize.x); - uvec2 tileOffset = uvec2(aTileIndex % tilesPerRow, aTileIndex / tilesPerRow); - return vec2(tileOffset) * uTileSize; -} - -void main() { - vec2 tileOrigin = computeTileOffset(aTileIndex, uFramebufferSize.x); - - vec2 from = vec2(aFromPx & 15u, aFromPx >> 4u) + aFromSubpx; - vec2 to = vec2(aToPx & 15u, aToPx >> 4u) + aToSubpx; - - vec2 position; - bool zeroArea = !(abs(from.x - to.x) > 0.1) || !(abs(uTileSize.y - min(from.y, to.y)) > 0.1); - if (aTessCoord.x < 0.5) - position.x = floor(min(from.x, to.x)); - else - position.x = ceil(max(from.x, to.x)); - if (aTessCoord.y < 0.5) - position.y = floor(min(from.y, to.y)); - else - position.y = uTileSize.y; - - vFrom = from - position; - vTo = to - position; - - if (zeroArea) - gl_Position = vec4(0.0); - else - gl_Position = vec4((tileOrigin + position) / uFramebufferSize * 2.0 - 1.0, 0.0, 1.0); -} diff --git a/demo2/tiling.ts b/demo2/tiling.ts deleted file mode 100644 index 02112983..00000000 --- a/demo2/tiling.ts +++ /dev/null @@ -1,710 +0,0 @@ -// pathfinder/demo2/tiling.ts -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -import {Point2D, Rect, Size2D, cross, lerp} from "./geometry"; -import {PathSegment} from "./path-utils"; -import {panic, staticCast, unwrapNull} from "./util"; - -export const TILE_SIZE: Size2D = {width: 16.0, height: 16.0}; - -export interface SVGPath { - abs(): SVGPath; - translate(x: number, y: number): SVGPath; - matrix(m: number[]): SVGPath; - iterate(f: (segment: string[], index: number, x: number, y: number) => string[][] | void): - SVGPath; - unshort(): SVGPath; -} - -const SVGPath: (path: string) => SVGPath = require('svgpath'); - -interface EndpointIndex { - subpathIndex: number; - endpointIndex: number; -}; - -export class Tiler { - private path: SVGPath; - private endpoints: SubpathEndpoints[]; - private sortedEdges: Edge[]; - private boundingRect: Rect | null; - private strips: Strip[]; - private tileStrips: TileStrip[]; - - constructor(path: SVGPath) { - this.path = path; - //console.log("tiler: path=", path); - - // Accumulate endpoints. - this.endpoints = []; - let currentSubpathEndpoints = new SubpathEndpoints; - path.iterate(segString => { - const segment = new PathSegment(segString); - //console.log("segment", segment); - switch (segment.command) { - case 'M': - if (!currentSubpathEndpoints.isEmpty()) { - this.endpoints.push(currentSubpathEndpoints); - currentSubpathEndpoints = new SubpathEndpoints; - } - currentSubpathEndpoints.controlPoints.push(null); - currentSubpathEndpoints.endpoints.push(segment.points[0]); - break; - case 'L': - case 'S': - // TODO(pcwalton): Canonicalize 'S'. - currentSubpathEndpoints.controlPoints.push(null); - currentSubpathEndpoints.endpoints.push(unwrapNull(segment.to())); - break; - case 'Q': - currentSubpathEndpoints.controlPoints.push(segment.points[0]); - currentSubpathEndpoints.endpoints.push(unwrapNull(segment.to())); - break; - case 'Z': - break; - default: - panic("Unexpected path command: " + segment.command); - break; - } - }); - if (!currentSubpathEndpoints.isEmpty()) - this.endpoints.push(currentSubpathEndpoints); - - // Sort edges, and accumulate bounding rect. - this.sortedEdges = []; - this.boundingRect = null; - for (let subpathIndex = 0; subpathIndex < this.endpoints.length; subpathIndex++) { - const subpathEndpoints = this.endpoints[subpathIndex]; - for (let endpointIndex = 0; - endpointIndex < subpathEndpoints.endpoints.length; - endpointIndex++) { - this.sortedEdges.push(this.nextEdgeFromEndpoint({subpathIndex, endpointIndex})); - - const endpoint = subpathEndpoints.endpoints[endpointIndex]; - if (this.boundingRect == null) - this.boundingRect = new Rect(endpoint, {width: 0, height: 0}); - else - this.boundingRect = this.boundingRect.unionWithPoint(endpoint); - } - } - this.sortedEdges.sort((edgeA, edgeB) => { - return Math.min(edgeA.from.y, edgeA.to.y) - Math.min(edgeB.from.y, edgeB.to.y); - }); - - /* - // Dump endpoints. - const allEndpoints = this.sortedEndpointIndices.map(index => { - return { - index: index, - endpoint: this.endpoints[index.subpathIndex].endpoints[index.endpointIndex], - }; - }); - //console.log("allEndpoints", allEndpoints); - */ - - this.strips = []; - this.tileStrips = []; - } - - tile(): void { - if (this.boundingRect == null) - return; - - const activeIntervals = new Intervals(this.boundingRect.maxX());; - let activeEdges: Edge[] = []; - let nextEdgeIndex = 0; - this.strips = []; - - let tileTop = this.boundingRect.origin.y - this.boundingRect.origin.y % TILE_SIZE.height; - while (tileTop < this.boundingRect.maxY()) { - const strip = new Strip(tileTop); - const tileBottom = tileTop + TILE_SIZE.height; - - // Populate tile strip with active intervals. - // TODO(pcwalton): Compress this. - for (const interval of activeIntervals.intervalRanges()) { - if (interval.winding === 0) - continue; - const startPoint = new Point2D(interval.start, tileTop); - const endPoint = new Point2D(interval.end, tileTop); - if (interval.winding < 0) - strip.pushEdge(new Edge(startPoint, null, endPoint)); - else - strip.pushEdge(new Edge(endPoint, null, startPoint)); - } - - // Populate tile strip with active edges. - const oldEdges = activeEdges; - activeEdges = []; - for (const activeEdge of oldEdges) - this.processEdgeY(activeEdge, strip, activeEdges, activeIntervals, tileTop); - - while (nextEdgeIndex < this.sortedEdges.length) { - const edge = this.sortedEdges[nextEdgeIndex]; - if (edge.from.y > tileBottom && edge.to.y > tileBottom) - break; - - this.processEdgeY(edge, strip, activeEdges, activeIntervals, tileTop); - //console.log("new intervals:", JSON.stringify(activeIntervals)); - nextEdgeIndex++; - } - - this.strips.push(strip); - tileTop = tileBottom; - } - - // Cut up tile strips. - this.tileStrips = []; - for (const strip of this.strips) { - const tileStrip = this.divideStrip(strip); - if (!tileStrip.isEmpty()) - this.tileStrips.push(tileStrip); - } - } - - private divideStrip(strip: Strip): TileStrip { - // Sort edges. - const sortedEdges = strip.edges.slice(0); - sortedEdges.sort((edgeA, edgeB) => { - return Math.min(edgeA.from.x, edgeA.to.x) - Math.min(edgeB.from.x, edgeB.to.x); - }); - - const tileStrip = new TileStrip(strip.tileTop); - const boundingRect = unwrapNull(this.boundingRect); - let tileLeft = boundingRect.origin.x - boundingRect.origin.x % TILE_SIZE.width; - let activeEdges: Edge[] = []; - let nextEdgeIndex = 0; - - while (tileLeft < boundingRect.maxX()) { - const tile = new Tile(tileLeft); - const tileRight = tileLeft + TILE_SIZE.width; - - // Populate tile with active edges. - const oldEdges = activeEdges; - activeEdges = []; - for (const activeEdge of oldEdges) - this.processEdgeX(activeEdge, tile, activeEdges); - - while (nextEdgeIndex < sortedEdges.length) { - const edge = sortedEdges[nextEdgeIndex]; - if (edge.from.x > tileRight && edge.to.x > tileRight) - break; - - this.processEdgeX(edge, tile, activeEdges); - nextEdgeIndex++; - } - - if (!tile.isEmpty()) - tileStrip.pushTile(tile); - - tileLeft = tileRight; - } - - return tileStrip; - } - - getStrips(): Strip[] { - return this.strips; - } - - getTileStrips(): TileStrip[] { - return this.tileStrips; - } - - getBoundingRect(): Rect { - if (this.boundingRect == null) - return new Rect(new Point2D(0, 0), {width: 0, height: 0}); - - const tileLeft = this.boundingRect.origin.x - this.boundingRect.origin.x % TILE_SIZE.width; - const tileRight = Math.ceil(this.boundingRect.maxX() / TILE_SIZE.width) * TILE_SIZE.width; - const tileTop = this.boundingRect.origin.y - this.boundingRect.origin.y % TILE_SIZE.height; - const tileBottom = Math.ceil(this.boundingRect.maxY() / TILE_SIZE.height) * - TILE_SIZE.height; - return new Rect(new Point2D(tileLeft, tileTop), - {width: tileRight - tileLeft, height: tileBottom - tileTop}); - } - - private processEdgeX(edge: Edge, tile: Tile, activeEdges: Edge[]): void { - const tileRight = tile.tileLeft + TILE_SIZE.width; - const clipped = this.clipEdgeX(edge, tileRight); - - if (clipped.left != null) - tile.pushEdge(clipped.left); - - if (clipped.right != null) - activeEdges.push(clipped.right); - } - - private processEdgeY(edge: Edge, - tileStrip: Strip, - activeEdges: Edge[], - intervals: Intervals, - tileTop: number): - void { - const tileBottom = tileTop + TILE_SIZE.height; - const clipped = this.clipEdgeY(edge, tileBottom); - - if (clipped.upper != null) { - //console.log("pushing clipped upper edge:", JSON.stringify(clipped.upper)); - tileStrip.pushEdge(clipped.upper); - - if (clipped.upper.from.x <= clipped.upper.to.x) - intervals.add(new IntervalRange(clipped.upper.from.x, clipped.upper.to.x, -1)); - else - intervals.add(new IntervalRange(clipped.upper.to.x, clipped.upper.from.x, 1)); - } - - if (clipped.lower != null) - activeEdges.push(clipped.lower); - } - - private clipEdgeX(edge: Edge, x: number): ClippedEdgesX { - const EPSILON: number = 0.00001; - - if (edge.from.x < x && edge.to.x < x) - return {left: edge, right: null}; - if (edge.from.x > x && edge.to.x > x) - return {left: null, right: edge}; - - let minT = 0.0, maxT = 1.0; - while (maxT - minT > EPSILON) { - const midT = lerp(minT, maxT, 0.5); - const edges = edge.subdivideAt(midT); - if ((edges.prev.from.x < x && edges.prev.to.x > x) || - (edges.prev.from.x > x && edges.prev.to.x < x)) { - maxT = midT; - } else { - minT = midT; - } - } - - const midT = lerp(minT, maxT, 0.5); - const edges = edge.subdivideAt(midT); - if (edge.from.x < x) - return {left: edges.prev, right: edges.next}; - return {left: edges.next, right: edges.prev}; - } - - private clipEdgeY(edge: Edge, y: number): ClippedEdgesY { - const EPSILON: number = 0.00001; - - if (edge.from.y < y && edge.to.y < y) - return {upper: edge, lower: null}; - if (edge.from.y > y && edge.to.y > y) - return {upper: null, lower: edge}; - - let minT = 0.0, maxT = 1.0; - while (maxT - minT > EPSILON) { - const midT = lerp(minT, maxT, 0.5); - const edges = edge.subdivideAt(midT); - if ((edges.prev.from.y < y && edges.prev.to.y > y) || - (edges.prev.from.y > y && edges.prev.to.y < y)) { - maxT = midT; - } else { - minT = midT; - } - } - - const midT = lerp(minT, maxT, 0.5); - const edges = edge.subdivideAt(midT); - if (edge.from.y < y) - return {upper: edges.prev, lower: edges.next}; - return {upper: edges.next, lower: edges.prev}; - } - - private nextEdgeFromEndpoint(endpointIndex: EndpointIndex): Edge { - const subpathEndpoints = this.endpoints[endpointIndex.subpathIndex]; - const nextEndpointIndex = - subpathEndpoints.nextEndpointIndexOf(endpointIndex.endpointIndex); - return new Edge(subpathEndpoints.endpoints[endpointIndex.endpointIndex], - subpathEndpoints.controlPoints[nextEndpointIndex], - subpathEndpoints.endpoints[nextEndpointIndex]); - } -} - -class SubpathEndpoints { - endpoints: Point2D[]; - controlPoints: (Point2D | null)[]; - - constructor() { - this.endpoints = []; - this.controlPoints = []; - } - - isEmpty(): boolean { - return this.endpoints.length < 2; - } - - prevEndpointIndexOf(index: number): number { - const prevIndex = index - 1; - return prevIndex < 0 ? this.endpoints.length - 1 : prevIndex; - } - - nextEndpointIndexOf(index: number): number { - const nextIndex = index + 1; - return nextIndex >= this.endpoints.length ? 0 : nextIndex; - } - - prevEndpointOf(index: number): Point2D { - return this.endpoints[this.prevEndpointIndexOf(index)]; - } - - nextEndpointOf(index: number): Point2D { - return this.endpoints[this.nextEndpointIndexOf(index)]; - } -} - -export class Edge { - from: Point2D; - ctrl: Point2D | null; - to: Point2D; - - constructor(from: Point2D, ctrl: Point2D | null, to: Point2D) { - this.from = from; - this.ctrl = ctrl; - this.to = to; - Object.freeze(this); - } - - subdivideAt(t: number): SubdividedEdges { - if (this.ctrl == null) { - const mid = this.from.lerp(this.to, t); - return { - prev: new Edge(this.from, null, mid), - next: new Edge(mid, null, this.to), - }; - } - - const ctrlA = this.from.lerp(this.ctrl, t); - const ctrlB = this.ctrl.lerp(this.to, t); - const mid = ctrlA.lerp(ctrlB, t); - return { - prev: new Edge(this.from, ctrlA, mid), - next: new Edge(mid, ctrlB, this.to), - } - } - - toSVGPieces(): string[] { - if (this.ctrl == null) - return ['L', "" + this.to.x, "" + this.to.y]; - return ['Q', "" + this.ctrl.x, "" + this.ctrl.y, "" + this.to.x, "" + this.to.y]; - } -} - -interface SubdividedEdges { - prev: Edge; - next: Edge; -} - -class Strip { - edges: Edge[]; - tileTop: number; - - constructor(tileTop: number) { - this.edges = []; - this.tileTop = tileTop; - } - - pushEdge(edge: Edge): void { - this.edges.push(new Edge(edge.from.translate(0, -this.tileTop), - edge.ctrl == null ? null : edge.ctrl.translate(0, -this.tileTop), - edge.to.translate(0, -this.tileTop))); - } - - tileBottom(): number { - return this.tileTop + TILE_SIZE.height; - } -} - -export class TileStrip { - tiles: Tile[]; - tileTop: number; - - constructor(tileTop: number) { - this.tiles = []; - this.tileTop = tileTop; - } - - pushTile(tile: Tile): void { - this.tiles.push(tile); - } - - tileBottom(): number { - return this.tileTop + TILE_SIZE.height; - } - - isEmpty(): boolean { - return this.tiles.length === 0; - } -} - -export class Tile { - edges: Edge[]; - tileLeft: number; - - constructor(tileLeft: number) { - this.edges = []; - this.tileLeft = tileLeft; - } - - pushEdge(edge: Edge): void { - this.edges.push(new Edge(edge.from.translate(-this.tileLeft, 0), - edge.ctrl == null ? null : edge.ctrl.translate(-this.tileLeft, 0), - edge.to.translate(-this.tileLeft, 0))); - } - - isEmpty(): boolean { - return this.edges.length === 0; - } - - isFilled(): boolean { - if (this.edges.length !== 1) - return false; - const edge = this.edges[0]; - if (edge.ctrl != null) - return false; - //console.log("single edge:", JSON.stringify(edge)); - const left = edge.from.x < edge.to.x ? edge.from : edge.to; - const right = edge.from.x < edge.to.x ? edge.to : edge.from; - return left.approxEq(new Point2D(0, 0), 0.1) && - right.approxEq(new Point2D(TILE_SIZE.width, 0), 0.1); - } -} - -interface ClippedEdgesX { - left: Edge | null; - right: Edge | null; -} - -interface ClippedEdgesY { - upper: Edge | null; - lower: Edge | null; -} - -class Intervals { - private ranges: IntervalRange[]; - - constructor(width: number) { - this.ranges = [new IntervalRange(0, width, 0)]; - } - - intervalRanges(): IntervalRange[] { - return this.ranges; - } - - add(range: IntervalRange): void { - //console.log("IntervalRange.add(", range, ")"); - //console.log("... before ...", JSON.stringify(this)); - - this.splitAt(range.start); - this.splitAt(range.end); - - let startIndex = this.ranges.length, endIndex = this.ranges.length; - for (let i = 0; i < this.ranges.length; i++) { - if (range.start === this.ranges[i].start) - startIndex = i; - if (range.end === this.ranges[i].end) - endIndex = i + 1; - } - - // Adjust winding numbers. - for (let i = startIndex; i < endIndex; i++) - this.ranges[i].winding += range.winding; - - this.mergeAdjacent(); - - //console.log("... after ...", JSON.stringify(this)); - } - - clear(): void { - this.ranges = [new IntervalRange(0, this.ranges[this.ranges.length - 1].end, 0)]; - } - - private splitAt(value: number): void { - for (let i = 0; i < this.ranges.length; i++) { - if (this.ranges[i].start < value && value < this.ranges[i].end) { - const oldRange = this.ranges[i]; - const range0 = new IntervalRange(oldRange.start, value, oldRange.winding); - const range1 = new IntervalRange(value, oldRange.end, oldRange.winding); - this.ranges.splice(i, 1, range0, range1); - break; - } - } - } - - private mergeAdjacent(): void { - let i = 0; - while (i + 1 < this.ranges.length) { - if (this.ranges[i].end === this.ranges[i + 1].start && - this.ranges[i].winding === this.ranges[i + 1].winding) { - this.ranges[i].end = this.ranges[i + 1].end; - this.ranges.splice(i + 1, 1); - continue; - } - i++; - } - } -} - -class IntervalRange { - start: number; - end: number; - winding: number; - - constructor(start: number, end: number, winding: number) { - this.start = start; - this.end = end; - this.winding = winding; - } - - contains(value: number): boolean { - return value >= this.start && value < this.end; - } -} - -// Debugging - -const SVG_NS: string = "http://www.w3.org/2000/svg"; - -export class TileDebugger { - svg: SVGElement; - size: Size2D; - - constructor(document: HTMLDocument) { - this.svg = staticCast(document.createElementNS(SVG_NS, 'svg'), SVGElement); - - this.size = {width: 0, height: 0}; - - this.svg.style.position = 'absolute'; - this.svg.style.left = "0"; - this.svg.style.top = "0"; - this.updateSVGSize(); - } - - addTiler(tiler: Tiler, fillColor: string, id: string): void { - const boundingRect = tiler.getBoundingRect(); - this.size.width = Math.max(this.size.width, boundingRect.maxX()); - this.size.height = Math.max(this.size.height, boundingRect.maxY()); - - const tileStrips = tiler.getTileStrips(); - for (let tileStripIndex = 0; tileStripIndex < tileStrips.length; tileStripIndex++) { - const tileStrip = tileStrips[tileStripIndex]; - - for (let tileIndex = 0; tileIndex < tileStrip.tiles.length; tileIndex++) { - const tile = tileStrip.tiles[tileIndex]; - - let path = ""; - for (const edge of tile.edges) { - path += "M " + edge.from.x + " " + edge.from.y + " "; - path += "L " + edge.to.x + " " + edge.to.y + " "; - path += "L " + edge.to.x + " " + TILE_SIZE.height + " "; - path += "L " + edge.from.x + " " + TILE_SIZE.height + " "; - path += "Z "; - } - - const pathElement = staticCast(document.createElementNS(SVG_NS, 'path'), - SVGPathElement); - pathElement.setAttribute('d', path); - pathElement.setAttribute('fill', fillColor); - //pathElement.setAttribute('stroke', "rgb(0, 128.0, 0)"); - pathElement.setAttribute('data-tile-id', id); - pathElement.setAttribute('data-tile-index', "" + tileIndex); - pathElement.setAttribute('data-tile-strip-index', "" + tileStripIndex); - pathElement.setAttribute('transform', - "translate(" + tile.tileLeft + " " + tileStrip.tileTop + ")"); - this.svg.appendChild(pathElement); - } - } - - this.updateSVGSize(); - } - - private updateSVGSize(): void { - this.svg.style.width = this.size.width + "px"; - this.svg.style.height = this.size.height + "px"; - } -} - -function assertEq(actual: T, expected: T): void { - if (JSON.stringify(expected) !== JSON.stringify(actual)) { - console.error("expected", expected, "but found", actual); - throw new Error("Assertion failed!"); - } -} - -export function testIntervals(): void { - const intervals = new Intervals(7); - intervals.add(new IntervalRange(1, 2, 1)); - intervals.add(new IntervalRange(3, 4, 1)); - intervals.add(new IntervalRange(5, 6, 1)); - assertEq(intervals.intervalRanges(), [ - new IntervalRange(0, 1, 0), - new IntervalRange(1, 2, 1), - new IntervalRange(2, 3, 0), - new IntervalRange(3, 4, 1), - new IntervalRange(4, 5, 0), - new IntervalRange(5, 6, 1), - new IntervalRange(6, 7, 0), - ]); - - intervals.clear(); - intervals.add(new IntervalRange(1, 2, 1)); - intervals.add(new IntervalRange(2, 3, 1)); - assertEq(intervals.intervalRanges(), [ - new IntervalRange(0, 1, 0), - new IntervalRange(1, 3, 1), - new IntervalRange(3, 7, 0), - ]); - - intervals.clear(); - intervals.add(new IntervalRange(1, 4, 1)); - intervals.add(new IntervalRange(3, 5, 1)); - assertEq(intervals.intervalRanges(), [ - new IntervalRange(0, 1, 0), - new IntervalRange(1, 3, 1), - new IntervalRange(3, 4, 2), - new IntervalRange(4, 5, 1), - new IntervalRange(5, 7, 0), - ]); - - intervals.clear(); - intervals.add(new IntervalRange(2, 3.5, 1)); - intervals.add(new IntervalRange(3, 5, 1)); - intervals.add(new IntervalRange(6, 7, 1)); - assertEq(intervals.intervalRanges(), [ - new IntervalRange(0, 2, 0), - new IntervalRange(2, 3, 1), - new IntervalRange(3, 3.5, 2), - new IntervalRange(3.5, 5, 1), - new IntervalRange(5, 6, 0), - new IntervalRange(6, 7, 1), - ]); - - intervals.clear(); - intervals.add(new IntervalRange(2, 5, 1)); - intervals.add(new IntervalRange(3, 3.5, -1)); - assertEq(intervals.intervalRanges(), [ - new IntervalRange(0, 2, 0), - new IntervalRange(2, 3, 1), - new IntervalRange(3, 3.5, 0), - new IntervalRange(3.5, 5, 1), - new IntervalRange(5, 7, 0), - ]); - - intervals.clear(); - intervals.add(new IntervalRange(2, 5, 1)); - intervals.add(new IntervalRange(3, 3.5, -1)); - intervals.add(new IntervalRange(3, 3.5, 1)); - assertEq(intervals.intervalRanges(), [ - new IntervalRange(0, 2, 0), - new IntervalRange(2, 5, 1), - new IntervalRange(5, 7, 0), - ]); -} diff --git a/demo2/tsconfig.json b/demo2/tsconfig.json deleted file mode 100644 index 5f6247d1..00000000 --- a/demo2/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "target": "es6" - }, -} diff --git a/demo2/util.ts b/demo2/util.ts deleted file mode 100644 index 5312d61e..00000000 --- a/demo2/util.ts +++ /dev/null @@ -1,31 +0,0 @@ -// pathfinder/demo2/util.ts -// -// Copyright © 2018 The Pathfinder Project Developers. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -export function panic(msg: string): never { - throw new Error(msg); -} - -export function staticCast(value: any, constructor: { new(...args: any[]): T }): T { - if (!(value instanceof constructor)) - panic("Invalid dynamic cast"); - return value; -} - -export function unwrapNull(value: T | null): T { - if (value == null) - throw new Error("Unexpected null"); - return value; -} - -export function unwrapUndef(value: T | undefined): T { - if (value == null) - throw new Error("Unexpected undefined"); - return value; -}