import * as React from "react";
import * as ReactDOM from "react-dom";
import { FilterResponse, FilterRequestProps } from "../../types";
import { Parser } from "collit";
import { isValidColor, normalizeHex } from "../../spinoffs/wcag-contrast";
function getMorphProps(radius: number) {
return {
operator: radius < 0 ? "erode" : "dilate",
radius: Math.abs(radius)
};
}
export function Double({
fill,
strokeWidth = 1,
getNamespacedId
}: FilterRequestProps): FilterResponse {
const source = "SourceGraphic";
const hasFill = ["none", "transparent"].indexOf(fill) === -1;
let filterPrimitives;
const inPrimitiveName = "inDouble";
const in2PrimitiveName = "in2Double";
let inRadius;
let compositeOperator;
// almost impossible to see a double line if it's under 1px wide.
const minStrokeWidth = Math.max(strokeWidth, 1);
if (!hasFill) {
compositeOperator = "out";
// Sets the width of the thick line.
inRadius = minStrokeWidth;
// Related to setting the width of the inner stripe that splits the thick
// line, although visual inspection shows it's setting something else,
// because the stripe width doesn't equal inRadius2 or 2 * inRadius2.
// NOTE: FF seems to need this, but Chrome does not.
const in2Radius = 1 / minStrokeWidth / 2;
filterPrimitives = [
// darken
,
];
} else {
compositeOperator = "atop";
// Appears to be related to setting the outside line.
const in2Radius = minStrokeWidth;
// Appears to be related to setting the inside line.
inRadius = -1 * minStrokeWidth;
filterPrimitives = [
];
}
filterPrimitives.push(
);
filterPrimitives.push(
);
return {
filterProperties: {
id: getNamespacedId(["double", hasFill, strokeWidth, "filter"].join("-")),
width: "200%",
height: "200%",
x: "-50%",
y: "-50%"
},
filterPrimitives: filterPrimitives
};
}
export function BlackToColor({
color,
getNamespacedId
}: FilterRequestProps): FilterResponse | "none" {
const source = "SourceGraphic";
if (!isValidColor(color)) {
return "none";
}
const { rgb, hex } = Parser.parseColor(color);
const { r, g, b, a } = rgb;
const id = getNamespacedId(
["BlackTo", normalizeHex(hex), "filter"].join("-")
);
return {
filterProperties: {
id: id,
filterUnits: "userSpaceOnUse"
},
filterPrimitives: [
]
};
}
export function WhiteToColor({
color,
getNamespacedId
}: FilterRequestProps): FilterResponse | "none" {
const source = "SourceGraphic";
if (!isValidColor(color)) {
return "none";
}
const { rgb, hex } = Parser.parseColor(color);
const { r, g, b, a } = rgb;
const id = getNamespacedId(
["WhiteTo", normalizeHex(hex), "filter"].join("-")
);
return {
filterProperties: {
id: id,
filterUnits: "userSpaceOnUse"
},
filterPrimitives: [
]
};
}
export function Highlight({
color,
getNamespacedId
}: FilterRequestProps): FilterResponse {
const source = "SourceGraphic";
return {
filterProperties: {
id: getNamespacedId(["highlight", color, "filter"].join("-")),
filterUnits: "userSpaceOnUse"
},
filterPrimitives: [
/* Desaturate all colours before highlighting */
,
,
,
,
,
]
};
}
export function Round({
strokeWidth = 1,
getNamespacedId
}: FilterRequestProps): FilterResponse {
const source = "SourceGraphic";
// Can we handle a strokeWidth of 0.4?
//const roundedStrokeWidth = Math.max(1, Math.round(strokeWidth || 1));
// C' = slope * C + intercept
// where C is the initial component (e.g., ‘feFuncR’),
// C' is the remapped component;
// both in the closed interval [0,1].
// http://www.w3.org/TR/filter-effects/#feComponentTransferElement
const darkInputSlope = 1.5;
const darkInputIntercept = 0;
const darkOutputSlope = 4;
const darkOutputIntercept = -0.7;
const normalizedWidth = 3;
//const strokeWidthNormalizationOperator = (strokeWidth > 2) ? 'contract' : 'dilate';
const strokeWidthNormalizationOperator =
strokeWidth > normalizedWidth ? "contract" : "dilate";
// strangely, this is what appears needed to normalize stroke width to a value
// large enough to be blurred without being destroyed:
const radius = strokeWidthNormalizationOperator === "dilate" ? 1 : 0;
// would have expected this, but it doesn't produce expected results:
//const radius = (strokeWidthNormalizationOperator === 'dilate') ? (normalizedWidth - strokeWidth) : strokeWidth - normalizedWidth;
//const radius = Math.abs((normalizedWidth - strokeWidth - 1) / 2 );
//const radius = Math.abs(normalizedWidth - strokeWidth);
const strokeWidthRevertOperator =
strokeWidthNormalizationOperator === "contract" ? "dilate" : "contract";
const normalizedDark =
strokeWidth === 1
? [
,
,
]
: [
,
];
return {
filterProperties: {
id: getNamespacedId(["round", strokeWidth, "filter"].join("-"))
},
filterPrimitives: normalizedDark.concat([
,
,
,
,
])
};
}