UNPKG

vuetify

Version:

Vue Material Component Framework

88 lines (72 loc) 3.44 kB
/** * WCAG 3.0 APCA perceptual contrast algorithm from https://github.com/Myndex/SAPC-APCA * @licence https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document * @see https://www.w3.org/WAI/GL/task-forces/silver/wiki/Visual_Contrast_of_Text_Subgroup */ // Types // MAGICAL NUMBERS // sRGB Conversion to Relative Luminance (Y) // Transfer Curve (aka "Gamma") for sRGB linearization // Simple power curve vs piecewise described in docs // Essentially, 2.4 best models actual display // characteristics in combination with the total method const mainTRC = 2.4; const Rco = 0.2126729; // sRGB Red Coefficient (from matrix) const Gco = 0.7151522; // sRGB Green Coefficient (from matrix) const Bco = 0.0721750; // sRGB Blue Coefficient (from matrix) // For Finding Raw SAPC Contrast from Relative Luminance (Y) // Constants for SAPC Power Curve Exponents // One pair for normal text, and one for reverse // These are the "beating heart" of SAPC const normBG = 0.55; const normTXT = 0.58; const revTXT = 0.57; const revBG = 0.62; // For Clamping and Scaling Values const blkThrs = 0.03; // Level that triggers the soft black clamp const blkClmp = 1.45; // Exponent for the soft black clamp curve const deltaYmin = 0.0005; // Lint trap const scaleBoW = 1.25; // Scaling for dark text on light const scaleWoB = 1.25; // Scaling for light text on dark const loConThresh = 0.078; // Threshold for new simple offset scale const loConFactor = 12.82051282051282; // = 1/0.078, const loConOffset = 0.06; // The simple offset const loClip = 0.001; // Output clip (lint trap #2) export function APCAcontrast(text, background) { // Linearize sRGB const Rtxt = (text.r / 255) ** mainTRC; const Gtxt = (text.g / 255) ** mainTRC; const Btxt = (text.b / 255) ** mainTRC; const Rbg = (background.r / 255) ** mainTRC; const Gbg = (background.g / 255) ** mainTRC; const Bbg = (background.b / 255) ** mainTRC; // Apply the standard coefficients and sum to Y let Ytxt = Rtxt * Rco + Gtxt * Gco + Btxt * Bco; let Ybg = Rbg * Rco + Gbg * Gco + Bbg * Bco; // Soft clamp Y when near black. // Now clamping all colors to prevent crossover errors if (Ytxt <= blkThrs) Ytxt += (blkThrs - Ytxt) ** blkClmp; if (Ybg <= blkThrs) Ybg += (blkThrs - Ybg) ** blkClmp; // Return 0 Early for extremely low ∆Y (lint trap #1) if (Math.abs(Ybg - Ytxt) < deltaYmin) return 0.0; // SAPC CONTRAST let outputContrast; // For weighted final values if (Ybg > Ytxt) { // For normal polarity, black text on white // Calculate the SAPC contrast value and scale const SAPC = (Ybg ** normBG - Ytxt ** normTXT) * scaleBoW; // NEW! SAPC SmoothScale™ // Low Contrast Smooth Scale Rollout to prevent polarity reversal // and also a low clip for very low contrasts (lint trap #2) // much of this is for very low contrasts, less than 10 // therefore for most reversing needs, only loConOffset is important outputContrast = SAPC < loClip ? 0.0 : SAPC < loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC - loConOffset; } else { // For reverse polarity, light text on dark // WoB should always return negative value. const SAPC = (Ybg ** revBG - Ytxt ** revTXT) * scaleWoB; outputContrast = SAPC > -loClip ? 0.0 : SAPC > -loConThresh ? SAPC - SAPC * loConFactor * loConOffset : SAPC + loConOffset; } return outputContrast * 100; } //# sourceMappingURL=APCA.js.map