From 52466a2564b03c247026c1d513e62ff8a58139aa Mon Sep 17 00:00:00 2001 From: Jakub Grzywacz Date: Thu, 25 Jul 2024 10:19:47 +0200 Subject: [PATCH] feat: introduce CSS filter API on FilterImage (#2359) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Summary Provide a **CSS**-like filter API in the `FilterImage` component. Unlike the SVG filter API, which can be complex and challenging even for simple tasks, the CSS API is straightforward and allows users to quickly achieve satisfactory results. The full API can be viewed here https://developer.mozilla.org/en-US/docs/Web/CSS/filter _We support all `` listed in the docs while we do not support functions from `` (`url()` and `src()`)._ All shorthands are implemented according to the W3 standard described here https://www.w3.org/TR/filter-effects-1/#ShorthandEquivalents This PR also changes the `filters` prop behavior as it adds `fe` in front of `name` attribute to not introduce any abstract above that specified in the docs. ```tsx ``` is now ```tsx ``` ## Examples Below are the simple examples of the usage through `StyleSheet` ```tsx import React from 'react'; import {StyleSheet, View} from 'react-native'; import {FilterImage} from 'react-native-svg/filter-image'; export default () => { return ( ); }; const styles = StyleSheet.create({ image: { width: 200, height: 200, filter: 'saturate(100) grayscale(100%)', }, }); ``` or directly in the `style` prop ```tsx import React from 'react'; import {StyleSheet, View} from 'react-native'; import {FilterImage} from 'react-native-svg/filter-image'; export default () => { return ( ); }; ``` ## Compatibility | OS | Implemented | | ------- | :---------: | | iOS | ✅ | | Android | ✅ | ## Checklist - [x] I have tested this on a device and a simulator - [x] I added documentation in `README.md` - [x] I updated the typed files (typescript) --- USAGE.md | 37 +- .../src/examples/FilterImage/FilterPicker.tsx | 15 +- .../src/examples/FilterImage/LocalImage.tsx | 37 +- .../src/examples/FilterImage/RemoteImage.tsx | 41 +- .../src/examples/FilterImage/index.tsx | 2 +- package.json | 3 +- src/filter-image/FilterImage.tsx | 53 +- src/filter-image/extract/extractFilters.ts | 26 + .../extract/extractFiltersString.d.ts | 3 + .../extract/extractFiltersString.js | 2042 +++++++++++++++++ .../extract/extractFiltersString.pegjs | 271 +++ .../{ => extract}/extractImage.ts | 0 src/filter-image/types.ts | 2 +- yarn.lock | 33 + 14 files changed, 2508 insertions(+), 57 deletions(-) create mode 100644 src/filter-image/extract/extractFilters.ts create mode 100644 src/filter-image/extract/extractFiltersString.d.ts create mode 100644 src/filter-image/extract/extractFiltersString.js create mode 100644 src/filter-image/extract/extractFiltersString.pegjs rename src/filter-image/{ => extract}/extractImage.ts (100%) diff --git a/USAGE.md b/USAGE.md index 4735fb8c..29f904d5 100644 --- a/USAGE.md +++ b/USAGE.md @@ -1296,7 +1296,37 @@ More info: `FilterImage` is a new component that is not strictly related to SVG. Its behavior should be the same as a regular `Image` component from React Native with one exception - the additional prop `filters`, which accepts an array of filters to apply to the image. -### Example +Filters can be applied in two ways + +- through `filters` prop +- or with CSS API through style prop + https://developer.mozilla.org/en-US/docs/Web/CSS/filter + +### Examples + +#### CSS filter API + +```tsx +import React from 'react'; +import { StyleSheet } from 'react-native'; +import { FilterImage } from 'react-native-svg/filter-image'; + +const myImage = require('./myImage.jpg'); + +export default () => { + return ; +}; + +const styles = StyleSheet.create({ + image: { + width: 200, + height: 200, + filter: 'saturate(3) grayscale(100%)', + }, +}); +``` + +#### `filters` prop ```tsx import React from 'react'; @@ -1311,9 +1341,9 @@ export default () => { style={styles.image} source={myImage} filters={[ - { name: 'colorMatrix', type: 'saturate', values: 0.2 }, + { name: 'feColorMatrix', type: 'saturate', values: 0.2 }, { - name: 'colorMatrix', + name: 'feColorMatrix', type: 'matrix', values: [ 0.2, 0.2, 0.2, 0, 0, 0.2, 0.2, 0.2, 0, 0, 0.2, 0.2, 0.2, 0, 0, 0, 0, @@ -1324,6 +1354,7 @@ export default () => { /> ); }; + const styles = StyleSheet.create({ image: { width: 200, diff --git a/apps/examples/src/examples/FilterImage/FilterPicker.tsx b/apps/examples/src/examples/FilterImage/FilterPicker.tsx index 76edce06..cea428cf 100644 --- a/apps/examples/src/examples/FilterImage/FilterPicker.tsx +++ b/apps/examples/src/examples/FilterImage/FilterPicker.tsx @@ -14,14 +14,14 @@ const img = require('../../assets/office.jpg'); const normal: Filters = []; const losAngeles: Filters = [ { - name: 'colorMatrix', + name: 'feColorMatrix', type: 'matrix', values: [1.8, 0, 0, 0, 0, 0, 1.3, 0, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1, 0], }, ]; const lagos: Filters = [ { - name: 'colorMatrix', + name: 'feColorMatrix', type: 'matrix', values: [ 1.4, 0, 0, 0, 0, 0, 1.2, 0, 0, 0, 0, 0, 1.5, 0, 0, 0, 0, 0, 0.9, 0, @@ -29,11 +29,10 @@ const lagos: Filters = [ }, ]; const tokyo: Filters = [ - {name: 'colorMatrix', type: 'saturate', values: [1.5]}, + {name: 'feColorMatrix', type: 'saturate', values: [1.5]}, { - name: 'colorMatrix', + name: 'feColorMatrix', type: 'matrix', - values: [ 0.2, 0.2, 0.2, 0, 0, 0.2, 0.2, 0.2, 0, 0, 0.2, 0.2, 0.2, 0, 0, 0, 0, 0, 1, 0, @@ -41,11 +40,11 @@ const tokyo: Filters = [ }, ]; const saturated: Filters = [ - {name: 'colorMatrix', type: 'saturate', values: [1.5]}, + {name: 'feColorMatrix', type: 'saturate', values: [1.5]}, ]; const boring: Filters = [ { - name: 'colorMatrix', + name: 'feColorMatrix', type: 'matrix', values: [ 0.6965, 0.3845, 0.0945, 0, 0, 0.1745, 0.8430000000000001, 0.084, 0, 0, @@ -131,10 +130,10 @@ const styles = StyleSheet.create({ const icon = ( ); diff --git a/apps/examples/src/examples/FilterImage/LocalImage.tsx b/apps/examples/src/examples/FilterImage/LocalImage.tsx index 21bd2965..22b45e27 100644 --- a/apps/examples/src/examples/FilterImage/LocalImage.tsx +++ b/apps/examples/src/examples/FilterImage/LocalImage.tsx @@ -4,26 +4,53 @@ import {FilterImage} from 'react-native-svg/filter-image'; const testImage = require('../../assets/image.jpg'); -const FilterImageLocalExample = () => { +const FilterImageLocalExampleStyleCSS = () => { + return ( + + + + ); +}; +FilterImageLocalExampleStyleCSS.title = 'With style filter CSS'; + +const FilterImageLocalExampleStyleSVG = () => { return ( ); }; -FilterImageLocalExample.title = 'Local image with filter'; +FilterImageLocalExampleStyleSVG.title = 'With style filter SVG'; + +const FilterImageLocalExamplePropSVG = () => { + return ( + + + + ); +}; +FilterImageLocalExamplePropSVG.title = 'With prop filters SVG'; const icon = ( ); -const samples = [FilterImageLocalExample]; +const samples = [ + FilterImageLocalExampleStyleCSS, + FilterImageLocalExampleStyleSVG, + FilterImageLocalExamplePropSVG, +]; export {icon, samples}; diff --git a/apps/examples/src/examples/FilterImage/RemoteImage.tsx b/apps/examples/src/examples/FilterImage/RemoteImage.tsx index a4f20d92..02ac5f40 100644 --- a/apps/examples/src/examples/FilterImage/RemoteImage.tsx +++ b/apps/examples/src/examples/FilterImage/RemoteImage.tsx @@ -1,32 +1,44 @@ import React from 'react'; -import {View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {FilterImage} from 'react-native-svg/filter-image'; const testSource = { uri: 'https://cdn.pixabay.com/photo/2023/03/17/11/39/mountain-7858482_1280.jpg', }; -const FilterImageRemoteExample = () => { +const FilterImageRemoteExampleCSS = () => { return ( ); }; -FilterImageRemoteExample.title = 'Remote image with filter'; +FilterImageRemoteExampleCSS.title = 'Remote image with CSS filter'; + +const FilterImageRemoteExample = () => { + return ( + + + + ); +}; +FilterImageRemoteExample.title = 'Remote image with prop filters'; const FilterImageFewFiltersExample = () => { return ( ); -const samples = [FilterImageRemoteExample, FilterImageFewFiltersExample]; +const styles = StyleSheet.create({ + image: { + width: 200, + height: 200, + }, +}); + +const samples = [ + FilterImageRemoteExampleCSS, + FilterImageRemoteExample, + FilterImageFewFiltersExample, +]; export {icon, samples}; diff --git a/apps/examples/src/examples/FilterImage/index.tsx b/apps/examples/src/examples/FilterImage/index.tsx index 042aaf14..2717da82 100644 --- a/apps/examples/src/examples/FilterImage/index.tsx +++ b/apps/examples/src/examples/FilterImage/index.tsx @@ -53,10 +53,10 @@ const styles = StyleSheet.create({ const icon = ( ); diff --git a/package.json b/package.json index bba55fff..f8cc813e 100644 --- a/package.json +++ b/package.json @@ -53,7 +53,7 @@ "format-js": "prettier --write README.md CONTRIBUTING.md CODE_OF_CONDUCT.md USAGE.md ./src/**/*.{ts,tsx} ./apps/**/*.tsx ./example/**/*.tsx ./*-example/**/*.tsx", "jest": "jest", "lint": "eslint --ext .ts,.tsx src", - "peg": "pegjs -o src/lib/extract/transform.js ./src/lib/extract/transform.peg", + "peg": "pegjs -o src/lib/extract/transform.js ./src/lib/extract/transform.peg && peggy -o src/filter-image/extract/extractFiltersString.js src/filter-image/extract/extractFiltersString.pegjs", "prepare": "npm run bob && husky install", "release": "npm login && release-it", "test": "npm run lint && npm run tsc", @@ -97,6 +97,7 @@ "husky": "^8.0.1", "jest": "^28.1.0", "lint-staged": "^13.0.3", + "peggy": "4.0.3", "pegjs": "^0.10.0", "prettier": "3.0.1", "react": "^18.2.0", diff --git a/src/filter-image/FilterImage.tsx b/src/filter-image/FilterImage.tsx index beee1241..36aa0450 100644 --- a/src/filter-image/FilterImage.tsx +++ b/src/filter-image/FilterImage.tsx @@ -1,52 +1,47 @@ -import { ImageProps, Image as RNImage, StyleSheet, View } from 'react-native'; -import { FeColorMatrix, Filter, Image, Svg } from '../index'; +import { + ImageProps, + ImageStyle, + Image as RNImage, + StyleProp, + StyleSheet, + View, +} from 'react-native'; +import { Filter, Image, Svg } from '../index'; +import { extractResizeMode } from './extract/extractImage'; import { Filters } from './types'; -import { extractResizeMode } from './extractImage'; +import { + extractFiltersCss, + mapFilterToComponent, +} from './extract/extractFilters'; export interface FilterImageProps extends ImageProps { - filters: Filters; + style?: StyleProp | undefined; + filters?: Filters; } -const getFilters = (filters: FilterImageProps['filters']) => { - return filters?.map((filter, index) => { - const { name, ...filterProps } = filter; - switch (name) { - case 'colorMatrix': - return ; - default: - return null; - } - }); -}; - export const FilterImage = (props: FilterImageProps) => { - const { source, style, ...imageProps } = props; + const { filters = [], source, style, ...imageProps } = props; + const styles = StyleSheet.flatten(style); + const extractedFilters = [...filters, ...extractFiltersCss(styles?.filter)]; const src = RNImage.resolveAssetSource(source); - const styles = StyleSheet.flatten(style); const width = props.width || styles?.width || src.width; const height = props.height || styles?.height || src.height; const preserveAspectRatio = extractResizeMode(props.resizeMode); return ( - + - {getFilters(props.filters)} + + {extractedFilters.map(mapFilterToComponent)} + 0 ? 'url(#filter)' : undefined} /> diff --git a/src/filter-image/extract/extractFilters.ts b/src/filter-image/extract/extractFilters.ts new file mode 100644 index 00000000..8335a604 --- /dev/null +++ b/src/filter-image/extract/extractFilters.ts @@ -0,0 +1,26 @@ +import React from 'react'; +import { tags } from '../../xml'; +import { FilterElement, Filters } from '../types'; +import { parse } from './extractFiltersString'; + +export const extractFiltersCss = (rawFilters?: Filters | string): Filters => { + if (!rawFilters) { + return []; + } + if (Array.isArray(rawFilters)) { + return rawFilters as Filters; + } + return parse(rawFilters); +}; + +export const mapFilterToComponent = ( + { name, ...props }: FilterElement, + index: number +) => { + return tags[name] + ? React.createElement(tags[name], { + ...props, + key: name + index, + }) + : null; +}; diff --git a/src/filter-image/extract/extractFiltersString.d.ts b/src/filter-image/extract/extractFiltersString.d.ts new file mode 100644 index 00000000..ee012236 --- /dev/null +++ b/src/filter-image/extract/extractFiltersString.d.ts @@ -0,0 +1,3 @@ +import { Filters } from '../types'; + +export function parse(filters: string): Filters; diff --git a/src/filter-image/extract/extractFiltersString.js b/src/filter-image/extract/extractFiltersString.js new file mode 100644 index 00000000..9233fb4b --- /dev/null +++ b/src/filter-image/extract/extractFiltersString.js @@ -0,0 +1,2042 @@ +// @generated by Peggy 4.0.3. +// +// https://peggyjs.org/ + +"use strict"; + + + + function buildDropShadow(offsetX, offsetY, blurRadius, color) { + return [ + { + name: "feGaussianBlur", + in: "SourceAlpha", + stdDeviation: blurRadius || 0 + }, + { + name: "feOffset", + dx: offsetX, + dy: offsetY, + result: "offsetblur" + }, + { + name: "feFlood", + floodColor: color || "transparent", + }, + { + name: "feComposite", + in2: "offsetblur", + operator: "in" + }, + { + name: "feMerge", + children: [ + { + name: "feMergeNode" + }, + { + name: "feMergeNode", + in: "SourceGraphic" + } + ] + } + ]; + } + +function peg$subclass(child, parent) { + function C() { this.constructor = child; } + C.prototype = parent.prototype; + child.prototype = new C(); +} + +function peg$SyntaxError(message, expected, found, location) { + var self = Error.call(this, message); + // istanbul ignore next Check is a necessary evil to support older environments + if (Object.setPrototypeOf) { + Object.setPrototypeOf(self, peg$SyntaxError.prototype); + } + self.expected = expected; + self.found = found; + self.location = location; + self.name = "SyntaxError"; + return self; +} + +peg$subclass(peg$SyntaxError, Error); + +function peg$padEnd(str, targetLength, padString) { + padString = padString || " "; + if (str.length > targetLength) { return str; } + targetLength -= str.length; + padString += padString.repeat(targetLength); + return str + padString.slice(0, targetLength); +} + +peg$SyntaxError.prototype.format = function(sources) { + var str = "Error: " + this.message; + if (this.location) { + var src = null; + var k; + for (k = 0; k < sources.length; k++) { + if (sources[k].source === this.location.source) { + src = sources[k].text.split(/\r\n|\n|\r/g); + break; + } + } + var s = this.location.start; + var offset_s = (this.location.source && (typeof this.location.source.offset === "function")) + ? this.location.source.offset(s) + : s; + var loc = this.location.source + ":" + offset_s.line + ":" + offset_s.column; + if (src) { + var e = this.location.end; + var filler = peg$padEnd("", offset_s.line.toString().length, ' '); + var line = src[s.line - 1]; + var last = s.line === e.line ? e.column : line.length + 1; + var hatLen = (last - s.column) || 1; + str += "\n --> " + loc + "\n" + + filler + " |\n" + + offset_s.line + " | " + line + "\n" + + filler + " | " + peg$padEnd("", s.column - 1, ' ') + + peg$padEnd("", hatLen, "^"); + } else { + str += "\n at " + loc; + } + } + return str; +}; + +peg$SyntaxError.buildMessage = function(expected, found) { + var DESCRIBE_EXPECTATION_FNS = { + literal: function(expectation) { + return "\"" + literalEscape(expectation.text) + "\""; + }, + + class: function(expectation) { + var escapedParts = expectation.parts.map(function(part) { + return Array.isArray(part) + ? classEscape(part[0]) + "-" + classEscape(part[1]) + : classEscape(part); + }); + + return "[" + (expectation.inverted ? "^" : "") + escapedParts.join("") + "]"; + }, + + any: function() { + return "any character"; + }, + + end: function() { + return "end of input"; + }, + + other: function(expectation) { + return expectation.description; + } + }; + + function hex(ch) { + return ch.charCodeAt(0).toString(16).toUpperCase(); + } + + function literalEscape(s) { + return s + .replace(/\\/g, "\\\\") + .replace(/"/g, "\\\"") + .replace(/\0/g, "\\0") + .replace(/\t/g, "\\t") + .replace(/\n/g, "\\n") + .replace(/\r/g, "\\r") + .replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); }); + } + + function classEscape(s) { + return s + .replace(/\\/g, "\\\\") + .replace(/\]/g, "\\]") + .replace(/\^/g, "\\^") + .replace(/-/g, "\\-") + .replace(/\0/g, "\\0") + .replace(/\t/g, "\\t") + .replace(/\n/g, "\\n") + .replace(/\r/g, "\\r") + .replace(/[\x00-\x0F]/g, function(ch) { return "\\x0" + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return "\\x" + hex(ch); }); + } + + function describeExpectation(expectation) { + return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); + } + + function describeExpected(expected) { + var descriptions = expected.map(describeExpectation); + var i, j; + + descriptions.sort(); + + if (descriptions.length > 0) { + for (i = 1, j = 1; i < descriptions.length; i++) { + if (descriptions[i - 1] !== descriptions[i]) { + descriptions[j] = descriptions[i]; + j++; + } + } + descriptions.length = j; + } + + switch (descriptions.length) { + case 1: + return descriptions[0]; + + case 2: + return descriptions[0] + " or " + descriptions[1]; + + default: + return descriptions.slice(0, -1).join(", ") + + ", or " + + descriptions[descriptions.length - 1]; + } + } + + function describeFound(found) { + return found ? "\"" + literalEscape(found) + "\"" : "end of input"; + } + + return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; +}; + +function peg$parse(input, options) { + options = options !== undefined ? options : {}; + + var peg$FAILED = {}; + var peg$source = options.grammarSource; + + var peg$startRuleFunctions = { start: peg$parsestart }; + var peg$startRuleFunction = peg$parsestart; + + var peg$c0 = "none"; + var peg$c1 = "grayscale("; + var peg$c2 = ")"; + var peg$c3 = "sepia("; + var peg$c4 = "saturate("; + var peg$c5 = "hue-rotate("; + var peg$c6 = "invert("; + var peg$c7 = "opacity("; + var peg$c8 = "brightness("; + var peg$c9 = "contrast("; + var peg$c10 = "blur("; + var peg$c11 = "drop-shadow("; + var peg$c12 = "%"; + var peg$c13 = "deg"; + var peg$c14 = "grad"; + var peg$c15 = "rad"; + var peg$c16 = "turn"; + var peg$c17 = "0"; + var peg$c18 = "#"; + var peg$c19 = "rgb("; + var peg$c20 = ","; + var peg$c21 = "rgba("; + var peg$c22 = "."; + var peg$c23 = "e"; + + var peg$r0 = /^[ \t\n\r]/; + var peg$r1 = /^[a-z\-]/; + var peg$r2 = /^[0-9a-fA-F]/; + var peg$r3 = /^[+\-]/; + var peg$r4 = /^[0-9]/; + + var peg$e0 = peg$otherExpectation("filters or 'none'"); + var peg$e1 = peg$otherExpectation("'none'"); + var peg$e2 = peg$literalExpectation("none", false); + var peg$e3 = peg$otherExpectation("filters"); + var peg$e4 = peg$otherExpectation("filter"); + var peg$e5 = peg$otherExpectation("grayscale"); + var peg$e6 = peg$literalExpectation("grayscale(", false); + var peg$e7 = peg$literalExpectation(")", false); + var peg$e8 = peg$otherExpectation("sepia"); + var peg$e9 = peg$literalExpectation("sepia(", false); + var peg$e10 = peg$otherExpectation("saturate"); + var peg$e11 = peg$literalExpectation("saturate(", false); + var peg$e12 = peg$otherExpectation("hue-rotate"); + var peg$e13 = peg$literalExpectation("hue-rotate(", false); + var peg$e14 = peg$otherExpectation("invert"); + var peg$e15 = peg$literalExpectation("invert(", false); + var peg$e16 = peg$otherExpectation("opacity"); + var peg$e17 = peg$literalExpectation("opacity(", false); + var peg$e18 = peg$otherExpectation("brightness"); + var peg$e19 = peg$literalExpectation("brightness(", false); + var peg$e20 = peg$otherExpectation("contrast"); + var peg$e21 = peg$literalExpectation("contrast(", false); + var peg$e22 = peg$otherExpectation("blur"); + var peg$e23 = peg$literalExpectation("blur(", false); + var peg$e24 = peg$otherExpectation("drop-shadow"); + var peg$e25 = peg$literalExpectation("drop-shadow(", false); + var peg$e26 = peg$otherExpectation("number or percentage"); + var peg$e27 = peg$literalExpectation("%", false); + var peg$e28 = peg$otherExpectation("angle or zero"); + var peg$e29 = peg$otherExpectation("angle"); + var peg$e30 = peg$literalExpectation("deg", false); + var peg$e31 = peg$literalExpectation("grad", false); + var peg$e32 = peg$literalExpectation("rad", false); + var peg$e33 = peg$literalExpectation("turn", false); + var peg$e34 = peg$otherExpectation("zero"); + var peg$e35 = peg$literalExpectation("0", false); + var peg$e36 = peg$otherExpectation("whitespace"); + var peg$e37 = peg$classExpectation([" ", "\t", "\n", "\r"], false, false); + var peg$e38 = peg$otherExpectation("identifier"); + var peg$e39 = peg$classExpectation([["a", "z"], "-"], false, false); + var peg$e40 = peg$otherExpectation("color"); + var peg$e41 = peg$literalExpectation("#", false); + var peg$e42 = peg$classExpectation([["0", "9"], ["a", "f"], ["A", "F"]], false, false); + var peg$e43 = peg$literalExpectation("rgb(", false); + var peg$e44 = peg$literalExpectation(",", false); + var peg$e45 = peg$literalExpectation("rgba(", false); + var peg$e46 = peg$classExpectation(["+", "-"], false, false); + var peg$e47 = peg$classExpectation([["0", "9"]], false, false); + var peg$e48 = peg$literalExpectation(".", false); + var peg$e49 = peg$literalExpectation("e", false); + + var peg$f0 = function() { return null; }; + var peg$f1 = function(head, tail) { + const results = [head]; + tail.forEach(element => { + if (Array.isArray(element[1])) { + results.push(...element[1]); + } else { + results.push(element[1]); + } + }); + return results; + }; + var peg$f2 = function(value) { + return { + name: "feColorMatrix", + type: "matrix", + values: [ + 0.2126 + 0.7874 * (1 - value), 0.7152 - 0.7152 * (1 - value), 0.0722 - 0.0722 * (1 - value), 0, 0, + 0.2126 - 0.2126 * (1 - value), 0.7152 + 0.2848 * (1 - value), 0.0722 - 0.0722 * (1 - value), 0, 0, + 0.2126 - 0.2126 * (1 - value), 0.7152 - 0.7152 * (1 - value), 0.0722 + 0.9278 * (1 - value), 0, 0, + 0, 0, 0, 1, 0 + ] + }; + }; + var peg$f3 = function(value) { + return { + name: "feColorMatrix", + type: "matrix", + values: [ + 0.393 + 0.607 * (1 - value), 0.769 - 0.769 * (1 - value), 0.189 - 0.189 * (1 - value), 0, 0, + 0.349 - 0.349 * (1 - value), 0.686 + 0.314 * (1 - value), 0.168 - 0.168 * (1 - value), 0, 0, + 0.272 - 0.272 * (1 - value), 0.534 - 0.534 * (1 - value), 0.131 + 0.869 * (1 - value), 0, 0, + 0, 0, 0, 1, 0 + ] + }; + }; + var peg$f4 = function(value) { + return { + name: "feColorMatrix", + type: "saturate", + values: [value] + }; + }; + var peg$f5 = function(value) { + return { + name: "feColorMatrix", + type: "hueRotate", + values: [value] + }; + }; + var peg$f6 = function(value) { + return { + name: "feComponentTransfer", + children: [ + { + name: "feFuncR", + type: "table", + tableValues: [value, 1 - value] + }, + { + name: "feFuncG", + type: "table", + tableValues: [value, 1 - value] + }, + { + name: "feFuncB", + type: "table", + tableValues: [value, 1 - value] + } + ] + }; + }; + var peg$f7 = function(value) { + return { + name: "feComponentTransfer", + children: [ + { + name: "feFuncA", + type: "table", + tableValues: [0, value] + } + ] + }; + }; + var peg$f8 = function(value) { + return { + name: "feComponentTransfer", + children: [ + { + name: "feFuncR", + type: "linear", + slope: value + }, + { + name: "feFuncG", + type: "linear", + slope: value + }, + { + name: "feFuncB", + type: "linear", + slope: value + } + ] + }; + }; + var peg$f9 = function(value) { + return { + name: "feComponentTransfer", + children: [ + { + name: "feFuncR", + type: "linear", + slope: value, + intercept: -(0.5 * value) + 0.5 + }, + { + name: "feFuncG", + type: "linear", + slope: value, + intercept: -(0.5 * value) + 0.5 + }, + { + name: "feFuncB", + type: "linear", + slope: value, + intercept: -(0.5 * value) + 0.5 + } + ] + }; + }; + var peg$f10 = function(value) { + return { + name: "feGaussianBlur", + stdDeviation: value + }; + }; + var peg$f11 = function(offsetX, offsetY, blurRadius, color) { + return buildDropShadow(offsetX, offsetY, blurRadius, color); + }; + var peg$f12 = function(color, offsetX, offsetY, blurRadius) { + return buildDropShadow(offsetX, offsetY, blurRadius, color); + }; + var peg$f13 = function(value) { + return value / 100; + }; + var peg$f14 = function(value) { + return value; + }; + var peg$f15 = function(value) { + return value * 180 / 200; + }; + var peg$f16 = function(value) { + return value * 180 / Math.PI; + }; + var peg$f17 = function(value) { + return value * 360; + }; + var peg$f18 = function() { + return text(); + }; + var peg$f19 = function() { return text(); }; + var peg$f20 = function(r, g, b) { return text(); }; + var peg$f21 = function(r, g, b, a) { return text(); }; + var peg$f22 = function() { return text(); }; + var peg$f23 = function() { + return parseFloat(text()); + }; + var peg$currPos = options.peg$currPos | 0; + var peg$savedPos = peg$currPos; + var peg$posDetailsCache = [{ line: 1, column: 1 }]; + var peg$maxFailPos = peg$currPos; + var peg$maxFailExpected = options.peg$maxFailExpected || []; + var peg$silentFails = options.peg$silentFails | 0; + + var peg$result; + + if (options.startRule) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$savedPos, peg$currPos); + } + + function offset() { + return peg$savedPos; + } + + function range() { + return { + source: peg$source, + start: peg$savedPos, + end: peg$currPos + }; + } + + function location() { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description, location) { + location = location !== undefined + ? location + : peg$computeLocation(peg$savedPos, peg$currPos); + + throw peg$buildStructuredError( + [peg$otherExpectation(description)], + input.substring(peg$savedPos, peg$currPos), + location + ); + } + + function error(message, location) { + location = location !== undefined + ? location + : peg$computeLocation(peg$savedPos, peg$currPos); + + throw peg$buildSimpleError(message, location); + } + + function peg$literalExpectation(text, ignoreCase) { + return { type: "literal", text: text, ignoreCase: ignoreCase }; + } + + function peg$classExpectation(parts, inverted, ignoreCase) { + return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; + } + + function peg$anyExpectation() { + return { type: "any" }; + } + + function peg$endExpectation() { + return { type: "end" }; + } + + function peg$otherExpectation(description) { + return { type: "other", description: description }; + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos]; + var p; + + if (details) { + return details; + } else { + if (pos >= peg$posDetailsCache.length) { + p = peg$posDetailsCache.length - 1; + } else { + p = pos; + while (!peg$posDetailsCache[--p]) {} + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column + }; + + while (p < pos) { + if (input.charCodeAt(p) === 10) { + details.line++; + details.column = 1; + } else { + details.column++; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + + return details; + } + } + + function peg$computeLocation(startPos, endPos, offset) { + var startPosDetails = peg$computePosDetails(startPos); + var endPosDetails = peg$computePosDetails(endPos); + + var res = { + source: peg$source, + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + if (offset && peg$source && (typeof peg$source.offset === "function")) { + res.start = peg$source.offset(res.start); + res.end = peg$source.offset(res.end); + } + return res; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildSimpleError(message, location) { + return new peg$SyntaxError(message, null, null, location); + } + + function peg$buildStructuredError(expected, found, location) { + return new peg$SyntaxError( + peg$SyntaxError.buildMessage(expected, found), + expected, + found, + location + ); + } + + function peg$parsestart() { + var s0, s1; + + peg$silentFails++; + s0 = peg$parsenone(); + if (s0 === peg$FAILED) { + s0 = peg$parsefiltersList(); + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e0); } + } + + return s0; + } + + function peg$parsenone() { + var s0, s1; + + peg$silentFails++; + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c0) { + s1 = peg$c0; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e2); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f0(); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e1); } + } + + return s0; + } + + function peg$parsefiltersList() { + var s0, s1, s2, s3, s4, s5; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parsefunction(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + s4 = peg$parse_(); + s5 = peg$parsefunction(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + s4 = peg$parse_(); + s5 = peg$parsefunction(); + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + peg$savedPos = s0; + s0 = peg$f1(s1, s2); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e3); } + } + + return s0; + } + + function peg$parsefunction() { + var s0, s1; + + peg$silentFails++; + s0 = peg$parsegrayscale(); + if (s0 === peg$FAILED) { + s0 = peg$parsesepia(); + if (s0 === peg$FAILED) { + s0 = peg$parsesaturate(); + if (s0 === peg$FAILED) { + s0 = peg$parsehueRotate(); + if (s0 === peg$FAILED) { + s0 = peg$parseinvert(); + if (s0 === peg$FAILED) { + s0 = peg$parseopacity(); + if (s0 === peg$FAILED) { + s0 = peg$parsebrightness(); + if (s0 === peg$FAILED) { + s0 = peg$parsecontrast(); + if (s0 === peg$FAILED) { + s0 = peg$parseblur(); + if (s0 === peg$FAILED) { + s0 = peg$parsedropShadow(); + } + } + } + } + } + } + } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e4); } + } + + return s0; + } + + function peg$parsegrayscale() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 10) === peg$c1) { + s2 = peg$c1; + peg$currPos += 10; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e6); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parsenumberPercentage(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c2; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f2(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e5); } + } + + return s0; + } + + function peg$parsesepia() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 6) === peg$c3) { + s2 = peg$c3; + peg$currPos += 6; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e9); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parsenumberPercentage(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c2; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f3(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e8); } + } + + return s0; + } + + function peg$parsesaturate() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 9) === peg$c4) { + s2 = peg$c4; + peg$currPos += 9; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e11); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parsenumberPercentage(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c2; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f4(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e10); } + } + + return s0; + } + + function peg$parsehueRotate() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 11) === peg$c5) { + s2 = peg$c5; + peg$currPos += 11; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e13); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parseangleZero(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c2; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f5(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e12); } + } + + return s0; + } + + function peg$parseinvert() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 7) === peg$c6) { + s2 = peg$c6; + peg$currPos += 7; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e15); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parsenumberPercentage(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c2; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f6(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e14); } + } + + return s0; + } + + function peg$parseopacity() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 8) === peg$c7) { + s2 = peg$c7; + peg$currPos += 8; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e17); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parsenumberPercentage(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c2; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f7(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e16); } + } + + return s0; + } + + function peg$parsebrightness() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 11) === peg$c8) { + s2 = peg$c8; + peg$currPos += 11; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e19); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parsenumberPercentage(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c2; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f8(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e18); } + } + + return s0; + } + + function peg$parsecontrast() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 9) === peg$c9) { + s2 = peg$c9; + peg$currPos += 9; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e21); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parsenumberPercentage(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s6 = peg$c2; + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s6 !== peg$FAILED) { + s7 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f9(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e20); } + } + + return s0; + } + + function peg$parseblur() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 5) === peg$c10) { + s2 = peg$c10; + peg$currPos += 5; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e23); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parseNUM(); + if (s4 !== peg$FAILED) { + s5 = peg$parseIDENTIFIER(); + if (s5 === peg$FAILED) { + s5 = null; + } + s6 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s7 = peg$c2; + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s7 !== peg$FAILED) { + s8 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f10(s4); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e22); } + } + + return s0; + } + + function peg$parsedropShadow() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 12) === peg$c11) { + s2 = peg$c11; + peg$currPos += 12; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e25); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parseNUM(); + if (s4 !== peg$FAILED) { + s5 = peg$parseIDENTIFIER(); + if (s5 === peg$FAILED) { + s5 = null; + } + s6 = peg$parse_(); + s7 = peg$parseNUM(); + if (s7 !== peg$FAILED) { + s8 = peg$parseIDENTIFIER(); + if (s8 === peg$FAILED) { + s8 = null; + } + s9 = peg$parse_(); + s10 = peg$parseNUM(); + if (s10 === peg$FAILED) { + s10 = null; + } + s11 = peg$parseIDENTIFIER(); + if (s11 === peg$FAILED) { + s11 = null; + } + s12 = peg$parse_(); + s13 = peg$parseCOLOR(); + if (s13 === peg$FAILED) { + s13 = null; + } + s14 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s15 = peg$c2; + peg$currPos++; + } else { + s15 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s15 !== peg$FAILED) { + s16 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f11(s4, s7, s10, s13); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parse_(); + if (input.substr(peg$currPos, 12) === peg$c11) { + s2 = peg$c11; + peg$currPos += 12; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e25); } + } + if (s2 !== peg$FAILED) { + s3 = peg$parse_(); + s4 = peg$parseCOLOR(); + if (s4 !== peg$FAILED) { + s5 = peg$parse_(); + s6 = peg$parseNUM(); + if (s6 !== peg$FAILED) { + s7 = peg$parseIDENTIFIER(); + if (s7 === peg$FAILED) { + s7 = null; + } + s8 = peg$parse_(); + s9 = peg$parseNUM(); + if (s9 !== peg$FAILED) { + s10 = peg$parseIDENTIFIER(); + if (s10 === peg$FAILED) { + s10 = null; + } + s11 = peg$parse_(); + s12 = peg$parseNUM(); + if (s12 === peg$FAILED) { + s12 = null; + } + s13 = peg$parseIDENTIFIER(); + if (s13 === peg$FAILED) { + s13 = null; + } + s14 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s15 = peg$c2; + peg$currPos++; + } else { + s15 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s15 !== peg$FAILED) { + s16 = peg$parse_(); + peg$savedPos = s0; + s0 = peg$f12(s4, s6, s9, s12); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e24); } + } + + return s0; + } + + function peg$parsenumberPercentage() { + var s0, s1, s2; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parseNUM(); + if (s1 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 37) { + s2 = peg$c12; + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e27); } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f13(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parseNUM(); + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e26); } + } + + return s0; + } + + function peg$parseangleZero() { + var s0, s1; + + peg$silentFails++; + s0 = peg$parseangle(); + if (s0 === peg$FAILED) { + s0 = peg$parsezero(); + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e28); } + } + + return s0; + } + + function peg$parseangle() { + var s0, s1, s2; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parseNUM(); + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 3) === peg$c13) { + s2 = peg$c13; + peg$currPos += 3; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e30); } + } + if (s2 === peg$FAILED) { + s2 = null; + } + peg$savedPos = s0; + s0 = peg$f14(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseNUM(); + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 4) === peg$c14) { + s2 = peg$c14; + peg$currPos += 4; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e31); } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f15(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseNUM(); + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 3) === peg$c15) { + s2 = peg$c15; + peg$currPos += 3; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e32); } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f16(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseNUM(); + if (s1 !== peg$FAILED) { + if (input.substr(peg$currPos, 4) === peg$c16) { + s2 = peg$c16; + peg$currPos += 4; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e33); } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f17(s1); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e29); } + } + + return s0; + } + + function peg$parsezero() { + var s0, s1; + + peg$silentFails++; + if (input.charCodeAt(peg$currPos) === 48) { + s0 = peg$c17; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e35); } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e34); } + } + + return s0; + } + + function peg$parse_() { + var s0, s1; + + peg$silentFails++; + s0 = []; + s1 = input.charAt(peg$currPos); + if (peg$r0.test(s1)) { + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e37); } + } + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = input.charAt(peg$currPos); + if (peg$r0.test(s1)) { + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e37); } + } + } + peg$silentFails--; + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e36); } + + return s0; + } + + function peg$parseIDENTIFIER() { + var s0, s1, s2; + + peg$silentFails++; + s0 = peg$currPos; + s1 = []; + s2 = input.charAt(peg$currPos); + if (peg$r1.test(s2)) { + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e39); } + } + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = input.charAt(peg$currPos); + if (peg$r1.test(s2)) { + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e39); } + } + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f18(); + } + s0 = s1; + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e38); } + } + + return s0; + } + + function peg$parseCOLOR() { + var s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17; + + peg$silentFails++; + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 35) { + s1 = peg$c18; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e41); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = input.charAt(peg$currPos); + if (peg$r2.test(s3)) { + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e42); } + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = input.charAt(peg$currPos); + if (peg$r2.test(s3)) { + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e42); } + } + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f19(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c19) { + s1 = peg$c19; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e43); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + s3 = peg$parseNUM(); + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 44) { + s5 = peg$c20; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e44); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parse_(); + s7 = peg$parseNUM(); + if (s7 !== peg$FAILED) { + s8 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 44) { + s9 = peg$c20; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e44); } + } + if (s9 !== peg$FAILED) { + s10 = peg$parse_(); + s11 = peg$parseNUM(); + if (s11 !== peg$FAILED) { + s12 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s13 = peg$c2; + peg$currPos++; + } else { + s13 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s13 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f20(s3, s7, s11); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 5) === peg$c21) { + s1 = peg$c21; + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e45); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse_(); + s3 = peg$parseNUM(); + if (s3 !== peg$FAILED) { + s4 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 44) { + s5 = peg$c20; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e44); } + } + if (s5 !== peg$FAILED) { + s6 = peg$parse_(); + s7 = peg$parseNUM(); + if (s7 !== peg$FAILED) { + s8 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 44) { + s9 = peg$c20; + peg$currPos++; + } else { + s9 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e44); } + } + if (s9 !== peg$FAILED) { + s10 = peg$parse_(); + s11 = peg$parseNUM(); + if (s11 !== peg$FAILED) { + s12 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 44) { + s13 = peg$c20; + peg$currPos++; + } else { + s13 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e44); } + } + if (s13 !== peg$FAILED) { + s14 = peg$parse_(); + s15 = peg$parseNUM(); + if (s15 !== peg$FAILED) { + s16 = peg$parse_(); + if (input.charCodeAt(peg$currPos) === 41) { + s17 = peg$c2; + peg$currPos++; + } else { + s17 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e7); } + } + if (s17 !== peg$FAILED) { + peg$savedPos = s0; + s0 = peg$f21(s3, s7, s11, s15); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseIDENTIFIER(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$f22(); + } + s0 = s1; + } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e40); } + } + + return s0; + } + + function peg$parseNUM() { + var s0, s1, s2, s3, s4, s5, s6, s7; + + s0 = peg$currPos; + s1 = input.charAt(peg$currPos); + if (peg$r3.test(s1)) { + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e46); } + } + if (s1 === peg$FAILED) { + s1 = null; + } + s2 = peg$currPos; + s3 = []; + s4 = input.charAt(peg$currPos); + if (peg$r4.test(s4)) { + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = input.charAt(peg$currPos); + if (peg$r4.test(s4)) { + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + } + if (input.charCodeAt(peg$currPos) === 46) { + s4 = peg$c22; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e48); } + } + if (s4 !== peg$FAILED) { + s5 = []; + s6 = input.charAt(peg$currPos); + if (peg$r4.test(s6)) { + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + if (s6 !== peg$FAILED) { + while (s6 !== peg$FAILED) { + s5.push(s6); + s6 = input.charAt(peg$currPos); + if (peg$r4.test(s6)) { + peg$currPos++; + } else { + s6 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + } + } else { + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + s3 = [s3, s4, s5]; + s2 = s3; + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + } else { + peg$currPos = s2; + s2 = peg$FAILED; + } + if (s2 === peg$FAILED) { + s2 = []; + s3 = input.charAt(peg$currPos); + if (peg$r4.test(s3)) { + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = input.charAt(peg$currPos); + if (peg$r4.test(s3)) { + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + } + } else { + s2 = peg$FAILED; + } + } + if (s2 !== peg$FAILED) { + s3 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 101) { + s4 = peg$c23; + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e49); } + } + if (s4 !== peg$FAILED) { + s5 = input.charAt(peg$currPos); + if (peg$r3.test(s5)) { + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e46); } + } + if (s5 === peg$FAILED) { + s5 = null; + } + s6 = []; + s7 = input.charAt(peg$currPos); + if (peg$r4.test(s7)) { + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + if (s7 !== peg$FAILED) { + while (s7 !== peg$FAILED) { + s6.push(s7); + s7 = input.charAt(peg$currPos); + if (peg$r4.test(s7)) { + peg$currPos++; + } else { + s7 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$e47); } + } + } + } else { + s6 = peg$FAILED; + } + if (s6 !== peg$FAILED) { + s4 = [s4, s5, s6]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + if (s3 === peg$FAILED) { + s3 = null; + } + peg$savedPos = s0; + s0 = peg$f23(); + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + peg$result = peg$startRuleFunction(); + + if (options.peg$library) { + return /** @type {any} */ ({ + peg$result, + peg$currPos, + peg$FAILED, + peg$maxFailExpected, + peg$maxFailPos + }); + } + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail(peg$endExpectation()); + } + + throw peg$buildStructuredError( + peg$maxFailExpected, + peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, + peg$maxFailPos < input.length + ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) + : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) + ); + } +} + +module.exports = { + StartRules: ["start"], + SyntaxError: peg$SyntaxError, + parse: peg$parse +}; diff --git a/src/filter-image/extract/extractFiltersString.pegjs b/src/filter-image/extract/extractFiltersString.pegjs new file mode 100644 index 00000000..3f48a3ae --- /dev/null +++ b/src/filter-image/extract/extractFiltersString.pegjs @@ -0,0 +1,271 @@ +{{ + function buildDropShadow(offsetX, offsetY, blurRadius, color) { + return [ + { + name: "feGaussianBlur", + in: "SourceAlpha", + stdDeviation: blurRadius || 0 + }, + { + name: "feOffset", + dx: offsetX, + dy: offsetY, + result: "offsetblur" + }, + { + name: "feFlood", + floodColor: color || "transparent", + }, + { + name: "feComposite", + in2: "offsetblur", + operator: "in" + }, + { + name: "feMerge", + children: [ + { + name: "feMergeNode" + }, + { + name: "feMergeNode", + in: "SourceGraphic" + } + ] + } + ]; + } +}} + +start "filters or 'none'" + = none + / filtersList + +none "'none'" + = "none" { return null; } + +filtersList "filters" + = head:(function) tail:(_ function)* { + const results = [head]; + tail.forEach(element => { + if (Array.isArray(element[1])) { + results.push(...element[1]); + } else { + results.push(element[1]); + } + }); + return results; + } + +function "filter" + = grayscale + / sepia + / saturate + / hueRotate + / invert + / opacity + / brightness + / contrast + / blur + / dropShadow + +// Convert CSS shorthands to primitive representation +// https://www.w3.org/TR/filter-effects-1/#ShorthandEquivalents + +grayscale "grayscale" + = _ "grayscale(" _ value:numberPercentage _ ")" _ { + return { + name: "feColorMatrix", + type: "matrix", + values: [ + 0.2126 + 0.7874 * (1 - value), 0.7152 - 0.7152 * (1 - value), 0.0722 - 0.0722 * (1 - value), 0, 0, + 0.2126 - 0.2126 * (1 - value), 0.7152 + 0.2848 * (1 - value), 0.0722 - 0.0722 * (1 - value), 0, 0, + 0.2126 - 0.2126 * (1 - value), 0.7152 - 0.7152 * (1 - value), 0.0722 + 0.9278 * (1 - value), 0, 0, + 0, 0, 0, 1, 0 + ] + }; + } + +sepia "sepia" + = _ "sepia(" _ value:numberPercentage _ ")" _ { + return { + name: "feColorMatrix", + type: "matrix", + values: [ + 0.393 + 0.607 * (1 - value), 0.769 - 0.769 * (1 - value), 0.189 - 0.189 * (1 - value), 0, 0, + 0.349 - 0.349 * (1 - value), 0.686 + 0.314 * (1 - value), 0.168 - 0.168 * (1 - value), 0, 0, + 0.272 - 0.272 * (1 - value), 0.534 - 0.534 * (1 - value), 0.131 + 0.869 * (1 - value), 0, 0, + 0, 0, 0, 1, 0 + ] + }; + } + +saturate "saturate" + = _ "saturate(" _ value:numberPercentage _ ")" _ { + return { + name: "feColorMatrix", + type: "saturate", + values: [value] + }; + } + +hueRotate "hue-rotate" + = _ "hue-rotate(" _ value:(angleZero) _ ")" _ { + return { + name: "feColorMatrix", + type: "hueRotate", + values: [value] + }; + } + +invert "invert" + = _ "invert(" _ value:numberPercentage _ ")" _ { + return { + name: "feComponentTransfer", + children: [ + { + name: "feFuncR", + type: "table", + tableValues: [value, 1 - value] + }, + { + name: "feFuncG", + type: "table", + tableValues: [value, 1 - value] + }, + { + name: "feFuncB", + type: "table", + tableValues: [value, 1 - value] + } + ] + }; + } + +opacity "opacity" + = _ "opacity(" _ value:numberPercentage _ ")" _ { + return { + name: "feComponentTransfer", + children: [ + { + name: "feFuncA", + type: "table", + tableValues: [0, value] + } + ] + }; + } + +brightness "brightness" + = _ "brightness(" _ value:numberPercentage _ ")" _ { + return { + name: "feComponentTransfer", + children: [ + { + name: "feFuncR", + type: "linear", + slope: value + }, + { + name: "feFuncG", + type: "linear", + slope: value + }, + { + name: "feFuncB", + type: "linear", + slope: value + } + ] + }; + } + +contrast "contrast" + = _ "contrast(" _ value:numberPercentage _ ")" _ { + return { + name: "feComponentTransfer", + children: [ + { + name: "feFuncR", + type: "linear", + slope: value, + intercept: -(0.5 * value) + 0.5 + }, + { + name: "feFuncG", + type: "linear", + slope: value, + intercept: -(0.5 * value) + 0.5 + }, + { + name: "feFuncB", + type: "linear", + slope: value, + intercept: -(0.5 * value) + 0.5 + } + ] + }; + } + +blur "blur" + = _ "blur(" _ value:NUM IDENTIFIER? _ ")" _ { + return { + name: "feGaussianBlur", + stdDeviation: value + }; + } + +dropShadow "drop-shadow" + = _ "drop-shadow(" _ offsetX:NUM IDENTIFIER? _ offsetY:NUM IDENTIFIER? _ blurRadius:NUM? IDENTIFIER? _ color:COLOR? _ ")" _ { + return buildDropShadow(offsetX, offsetY, blurRadius, color); + } + / _ "drop-shadow(" _ color:COLOR _ offsetX:NUM IDENTIFIER? _ offsetY:NUM IDENTIFIER? _ blurRadius:NUM? IDENTIFIER? _ ")" _ { + return buildDropShadow(offsetX, offsetY, blurRadius, color); + } + + +numberPercentage "number or percentage" + = value:NUM "%" { + return value / 100; + } + / value:NUM + +angleZero "angle or zero" + = angle + / zero + +angle "angle" + = value:NUM "deg"? { + return value; + } + / value:NUM "grad" { + return value * 180 / 200; + } + / value:NUM "rad" { + return value * 180 / Math.PI; + } + / value:NUM "turn" { + return value * 360; + } + +zero "zero" + = "0" + +_ "whitespace" + = [ \t\n\r]* + +IDENTIFIER "identifier" + = [a-z\-]+ { + return text(); + } + +COLOR "color" + = "#" [0-9a-fA-F]+ { return text(); } + / "rgb(" _ r:NUM _ "," _ g:NUM _ "," _ b:NUM _ ")" { return text(); } + / "rgba(" _ r:NUM _ "," _ g:NUM _ "," _ b:NUM _ "," _ a:NUM _ ")" { return text(); } + / IDENTIFIER { return text(); } + +NUM + = [+-]? ([0-9]* "." [0-9]+ / [0-9]+) ("e" [+-]? [0-9]+)? { + return parseFloat(text()); + } diff --git a/src/filter-image/extractImage.ts b/src/filter-image/extract/extractImage.ts similarity index 100% rename from src/filter-image/extractImage.ts rename to src/filter-image/extract/extractImage.ts diff --git a/src/filter-image/types.ts b/src/filter-image/types.ts index 1dc7803d..e95139e6 100644 --- a/src/filter-image/types.ts +++ b/src/filter-image/types.ts @@ -1,7 +1,7 @@ import { FilterPrimitiveCommonProps } from '../elements/filters/FilterPrimitive'; import { FeColorMatrixProps } from '../index'; -export type FilterElement = ({ name: 'colorMatrix' } & FeColorMatrixProps) & +export type FilterElement = ({ name: 'feColorMatrix' } & FeColorMatrixProps) & FilterPrimitiveCommonProps; export type Filters = Array; diff --git a/yarn.lock b/yarn.lock index e5d7aecb..a39577ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1920,6 +1920,13 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.15.1.tgz#3d745996b2bd11095b515515fd3d68d46092a02d" integrity sha512-n8Kur1/CZlYG32YCEj30CoUqA8R7UyDVZzoEU6SDP+13+kXDT2kFVu6MpcnEUTyGP3i058ID6Qjp5h6IJxdPPQ== +"@peggyjs/from-mem@1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@peggyjs/from-mem/-/from-mem-1.3.0.tgz#16470cf7dfa22fc75ca217a4e064a5f0c4e1111b" + integrity sha512-kzGoIRJjkg3KuGI4bopz9UvF3KguzfxalHRDEIdqEZUe45xezsQ6cx30e0RKuxPUexojQRBfu89Okn7f4/QXsw== + dependencies: + semver "7.6.0" + "@react-native-community/cli-clean@11.3.5": version "11.3.5" resolved "https://registry.yarnpkg.com/@react-native-community/cli-clean/-/cli-clean-11.3.5.tgz#07c8a01e433ea6c6e32eb647908be48952888cdd" @@ -3603,6 +3610,11 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -7946,6 +7958,15 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +peggy@4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/peggy/-/peggy-4.0.3.tgz#7bcd47718483ab405c960350c5250e3e487dec74" + integrity sha512-v7/Pt6kGYsfXsCrfb52q7/yg5jaAwiVaUMAPLPvy4DJJU6Wwr72t6nDIqIDkGfzd1B4zeVuTnQT0RGeOhe/uSA== + dependencies: + "@peggyjs/from-mem" "1.3.0" + commander "^12.1.0" + source-map-generator "0.8.0" + pegjs@^0.10.0: version "0.10.0" resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" @@ -8797,6 +8818,13 @@ semver@7.3.5: dependencies: lru-cache "^6.0.0" +semver@7.6.0: + version "7.6.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" + integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== + dependencies: + lru-cache "^6.0.0" + semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -9034,6 +9062,11 @@ socks@^2.3.3: ip "^2.0.0" smart-buffer "^4.2.0" +source-map-generator@0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/source-map-generator/-/source-map-generator-0.8.0.tgz#10d5ca0651e2c9302ea338739cbd4408849c5d00" + integrity sha512-psgxdGMwl5MZM9S3FWee4EgsEaIjahYV5AzGnwUvPhWeITz/j6rKpysQHlQ4USdxvINlb8lKfWGIXwfkrgtqkA== + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a"