Socket
Socket
Sign inDemoInstall

apca-w3

Package Overview
Dependencies
1
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.7 to 0.1.8

_config.yml

20

LICENSE.md

@@ -5,5 +5,8 @@ Code and documentation in this repositiory is copyright © 2019-2021 by Andrew Somers and/or Myndex™. All Rights Reserved.

### The Short Summary:
Files in this repository are licensed to the W3/AGWG under their cooperative agreement for use with WCAG accessibility guidelines for web-based content only, and not for any other use.
### The Short Summary, TL;DR:
Files in this repository are licensed to the W3/AGWG under their cooperative agreement for use with WCAG accessibility guidelines for web-delivered and web-based content only, and not for any other use.
Use of the terms "APCA", "Advanced Perceptual Contrast Algorithm", "Accessible Perceptual Contrast Algorithm", to describe any contrast method, app, or device, is only permitted for code that is maintained and up to date.
--------------
______________

@@ -13,3 +16,3 @@

All Files in this Repository are licensed to the W3.org under their cooperative license agreement(s):
All Files in this Repository are licensed to the W3.org under their cooperative license agreement(s), and subject to the further limitations as defined in this license agreement.

@@ -47,4 +50,6 @@ - Reports in this Repository are licensed under the

_**NO ALTERATION; KEEP CURRENT**_
Any **apca-w3** files in this repositiory may be used or incorporated only in tools for web-based content or web related content in support of the WCAG accessibility guidelines, and such use must be without modification to the essential elements of the code or specific approved constants, except as required to port to a given language.
Any **apca-w3** files in this repository may be used or incorporated only in tools for web-based content or web related content in support of the WCAG accessibility guidelines, and such use must be without modification to the essential elements of the code or specific approved constants, except as required to port to a given language.
- Developers are highly encouraged to use the npm package(s) when possible: ` npm i apca-w3 `
- Deveopers incorporating this code into their applications, widgets, or other tools, have a duty to ensure that the most recent version of this code is used in their current or any future release.

@@ -57,5 +62,8 @@

_**USE OF APCA TERMINOLOGY**_
- Use of the acronym APCA, the terms "Advanced Perceptual Contrast Algorithm", "Accessible Perceptual Contrast Algorithm", "Readability Contrast", to describe any embodyment or instantiation of contrast determination, method, or math, including the APCA code base or libraries, **is only permitted for code that is properly using the APCA algorithm, version 0.0.98G-4g or later. **
_**USE OF THE APCA LOGO AND TRADEMARK**_
Use of the APCA or "Powered by APCA" logos or trademearks are prohibited without written consent from Myndex™ Technologies, Myndex™ Research, Andrew Somers, and/or the authorized agents or assigns.
- Developers wishing to use the APCA or "Powered by APCA" logos or trademearks must submit their application or tools for qualification to be granted a limited license to use the APCA or "Powered by APCA" logos or trademearks.
- Use of the APCA logo as shown at this repo to describe any contrast app, use, or method, or the "Powered by APCA" logo, and/or any related official logos or trademearks, **are prohibited without written consent** from Myndex™ Technologies, Myndex™ Research, Andrew Somers, and/or the authorized agents or assigns.
- Developers wishing to use the APCA or "Powered by APCA" logos or trademearks **must submit their application or tools for qualification** to be granted a limited license to use the APCA or "Powered by APCA" logos or trademearks in acssociation with their tools.
- Formal details on the APCA and "Powered by APCA" qualification process are pending. In the interim, make a qualification request in the discussion tab of this repo.

@@ -62,0 +70,0 @@

{
"name": "apca-w3",
"version": "0.1.7",
"version": "0.1.8",
"type": "module",

@@ -5,0 +5,0 @@ "description": "APCA the Advanced Perceptual Contrast Algorithm, a modern contrast method developed for WCAG 3 and other standards",

@@ -48,34 +48,11 @@ <p align="center">

### Current Algorithm Version: **0.0.98 G** (February 15, 2021) (w3)
### Current Algorithm Version: **0.0.98G-4g** (February 15, 2021) (w3)
This is the base algorithm version. The versions listed below are for the overal library file, as features and functions are added to aide in integration. These added features do not impact the base algorithm which is stable and undergoing public beta validation.
### Current Library Version: **0.1.7** G (w3) _beta_
### Current Library Version: **0.1.8** (w3) (98G4g) _beta_
- See [Version History](#version-history) for details.
#### 0.1.7 • May 27, 2022
Version number set to match font lookup table version
Added new test, run with ` npm test `
Maintenance updates, adjusted alphaBlend for compliance with CSS4
#### 0.1.4 • May 27, 2022
Updated the look-up tables for the fontLookupAPCA() function, and also added the data folder, where the raw data for the lookup tables can be found. Also some minor maintenance. (Note: the lookup tables are version 0.1.7 — will synchronize numbers on next publish).
#### 0.1.3 • May 17, 2022
Fixed the module imports for colorparsley and apca-w3 so they play well together.
No longer providing a minified version in the dist folder. Now just the file in the src folder.
#### 0.1.2 • April 23, 2022
**NEW!** `fontLookupAPCA(Lc)` Live font lookup table — sent it a contrast, it returns an array of font sizes (in px) for each of 9 weights (100 to 900).
**NEW!** `reverseAPCA(Lc,Y,use,returnAs)`
New in this version is a reverse contrast lookup. Specify a contrast, and one color (i.e. bg) and it will try to find a color with that contrast.
#### CHANGE for 0.1.1: 2021
**NEW!! Alpha channels! AdobeRGB!!**
#### CHANGE for 0.1.0: 2021
NEW! displayP3!
colorParsley() is now in its own package and must be imported separately.
### What is it?
APCA is a contrast assessment method for predicting the perceived contrast between sRGB colors on a computer monitor. It has been developed as an assessment method for W3 Silver/WCAG3 accessibility standards relating to content for computer displays and mobile devices, with a focus on readability and understandability.

@@ -93,2 +70,10 @@

Notes on the lookups:
- This is a basic table for fluent readability of text. Text that is intended to be read (primary content) should meet or exceed the values on the table.
- For body text, add Lc 15 for any value on the table lower than Lc 75.
- For instance, if using a 24px font, add Lc 15 to the minimum contrast value
- For sub-fluent text (i.e. not primary content) Lc values can be lowered by Lc 15, but in no case less than Lc 30.
- For non-fluent spot text (copyright bug, disabled text, placeholder) Lc values can be lowered by Lc25, but in no case less than Lc 30.
- Fonts larger than 24px and weight 300 or more have a maximum contrast of Lc 90.
<img width="400" alt="APCA Lookup Table" src="./images/APCAlookupByFont.jpeg">

@@ -197,28 +182,5 @@ <br>

### _String Theory_
The following are the available input types for colorParsley(), HSL is not implemented at the moment. All are automatically recognized:
See the colorparsley package for documentation on the available string inputs.
### INPUT as STRINGS:
- **No Alpha**
- ` '#abc' ` or ` 'abc' ` (interpreted as ` 'aabbcc' `)
- ` '#abcdef' ` or ` 'abcdef' ` (hash is ignored)
- ` 'rgb(123, 45, 67)' `
- ` 'aquamarine' ` or ` 'magenta' ` (full CSS4 named colors list)
- **With Alpha** _(alpha is NOT presently calculated, and assumed as fully opaque)_
- ` '#abcf' ` or ` 'abcf' ` (interpreted as ` 'aabbccff' `)
- ` '#123456ff' ` or ` '123456ff' ` (hash is ignored)
- ` 'rgba(123, 45, 67,1.0)' `
### INPUT as NUMBER:
- **As hex**
- ` 0xabcdef `
- **As integer**
- ` 11259375 `
No alpha parsing for _numbers_ in part as there are big and little endian issues that need to be resolved.
### colorParsley() string Parsing Removed, now a dependency
### colorParsley() string parsing moved to its own package
The function is called "colorParsley()" because what is that useless leafy thing the restaurant puts on the plate? Well, most mature software already has good parsing, and you may want to minimize the file leaving all that "parsley" at the restaurant...

@@ -235,4 +197,4 @@

calcAPCA( text, BG, places, isInt )
APCAcontrast ( txYs, bgYs, places )
alphaBlend( txt, BG, isInt )
APCAcontrast ( txYs, bgYs, places = -1 )
alphaBlend( txt, BG, round(bool) )

@@ -251,3 +213,3 @@ ` places ` defaults to -1, but you can send it 0 and the Lc is returned as a rounded value, and instead of a minus sign for polarity, 'WoB' for white on black is returned.

**These constants are for use with the web standard sRGB colorspace.**
These are the current contrast for use with current library version 0.1.4
These are the current contrast for use with current library version 0.1.8

@@ -317,3 +279,3 @@ ```javascript

### [LIVE VERSION][APCAsite]
There is a working version with examples and reference material on [the APCA site][APCAsite]
There is a working version with examples and reference material on [the APCA demo tool site][APCAsite]

@@ -324,10 +286,54 @@ [APCAsite]: https://www.myndex.com/APCA/

### APCA Base Math
_Click to Enlarge_
<img width="400" alt="the math for the basic APCA" src="./images/APCAcontrastPredictionEquation0.0.98G-4g-base.svg">
### APCA Base Math (sRGB)
<img width="480" alt="the math for the basic APCA" src="./images/APCAw3_0.1.17_APCA0.0.98G.svg">
### APCA is the _Advanced Perceptual Contrast Algorithm_
## THE REVOLUTION WILL BE READABLE™
---
## Version History
#### 0.1.8 • June 5, 2022
- Corrected the version numbering in the apca-w3.js file
- Added a LaTeX math svg of the base algorithm to this README file
- NOTE: the live tool at [www.myndex.com/APCA/][APCAsite] is now using a version of this apca-w3.js file, as well as colorparsley.
#### 0.1.7 • June 5, 2022
- Version number set to match font lookup table version
- Added new test, run with ` npm test `
- Maintenance updates, adjusted alphaBlend for compliance with CSS4
#### 0.1.4 • May 27, 2022
- Updated the look-up tables for the fontLookupAPCA() function, and also added the data folder, where the raw data for the lookup tables can be found.
- Also some minor maintenance. (Note: the lookup tables are version 0.1.7 — will synchronize numbers on next publish).
#### 0.1.3 • May 17, 2022
- Fixed the module imports for colorparsley and apca-w3 so they play well together.
- No longer providing a minified version in the dist folder. Now just the file in the src folder.
#### 0.1.2 • April 23, 2022
- **NEW!** `fontLookupAPCA(Lc)` Live font lookup table — send it a contrast, it returns an array of font sizes (in px) for each of 9 weights (100 to 900).
- **NEW!** `reverseAPCA(Lc,Y,use,returnAs)` New in this version is a reverse contrast lookup. Specify a contrast, and one color (i.e. bg) and it will try to find a color with that contrast.
#### CHANGE for 0.1.1: Jan 12, 2022
- **NEW!! Alpha channels! AdobeRGB!!**
#### CHANGE for 0.1.0: Jan 10, 2022
- NEW! displayP3!
- colorParsley() is now in its own package and must be imported separately.
- Replaced alpha versioning with semantic versioning for public beta.
- NOTE: while the version of this library file increments as features are added, the base algorithm is beta-stable and constants remain fixed at 0.0.98G-4g, from Feb. 15th, 2021.
#### 0.0.98G-4g-4: Dec 21, 2021
#### 0.0.98G-4g-3: Dec 13, 2021
#### 0.0.98G-4g-2: Dec 11, 2021
#### 0.0.98G-4g-betafish: Initial npm publish Dec 2, 2021
This moved over the base APCA and G4g constants (from Feb. 15th, 2021) to an npm package.
---
### APCA is the _Accessible Perceptual Contrast Algorithm_
## THE REVOLUTION WILL BE READABLE<sup>™</sup>
---
<sub>**Disclaimer:** _APCA is being evaluated as a replacement for WCAG 2 contrast math for future standards and guidelines, however, standards that will be incorporating APCA are still developmental. Because WCAG 2 contrast math does not accurately model human visual perception nor visual impairments, there will be discrepancies between WCAG 2 contrast math, and perceptually uniform models such as APCA. It is up to the end user to determine suitability of purpose for their region and conformance requirements._</sub>
///////////////////////////////////////////////////////////////////////////////
/** @preserve
///// SAPC APCA - Advanced Perceptual Contrast Algorithm
///// Beta 0.1.4 W3 • contrast function only
///// Beta 0.1.8 W3 • contrast function only
///// DIST: W3 • Revision date: May 28, 2022

@@ -42,4 +42,4 @@ ///// Function to parse color values and determine Lc contrast

///// W3 Licensed Version: https://github.com/Myndex/apca-w3
///// GITHUB: https://github.com/Myndex/SAPC-APCA
///// DEVELOPER SITE: https://www.myndex.com/WEB/Perception
///// GITHUB MAIN REPO: https://github.com/Myndex/SAPC-APCA
///// DEVELOPER SITE: https://git.myndex.com/
/////

@@ -62,3 +62,3 @@ ///// Acknowledgments and Thanks To:

/////
///// For Evaluations, refer to this as: SAPC-8, v0.1.4 G-series constant 4g
///// For Evaluations, refer to this as: SAPC-8, 0.0.98G-series constant 4g
///// SAPC • S-LUV Advanced Predictive Color

@@ -93,5 +93,5 @@ /////

////////// APCA 0.1.4 G 4g USAGE ///////////////////////////////////////////
////////// APCA 0.1.8 G 4g USAGE ///////////////////////////////////////////
///
/// The API for "APCA 0.1.4" is trivially simple.
/// The API for "APCA 0.1.8" is trivially simple.
/// Send text and background sRGB numeric values to the sRGBtoY() function,

@@ -130,9 +130,65 @@ /// and send the resulting text-Y and background-Y to the APCAcontrast function,

////////////////////////////////////////////////////////////////////////////////
///// BEGIN APCA 0.1.4 BLOCK \//////////////////////////////////////
//// \////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///// BEGIN APCA 0.1.8 BLOCK \/////////////////////////////////////
//// \///////////////////////////////////
/// \/////////////////////////////////
// \///////////////////////////////
///// DEPENDENCIES /////
// The following imports are not needed for the main APCA function,
// but are needed for the shortcut/alias calcAPCA(), and for the
// inverseAPCA function, which examines hue.
import { colorParsley, colorToHex, colorToRGB } from '../node_modules/colorparsley/src/colorparsley.js';
////////// ƒ APCAcontrast() /////////////////////////////////////////////
///// Module Scope Object Containing Constants /////
///// APCA 0.0.98G - 4g - W3 Compatible Constants
///// 𝒦 SA98G ///////////////////////////////////
const SA98G = {
mainTRC: 2.4, // 2.4 exponent for emulating actual monitor perception
// For reverseAPCA
get mainTRCencode() { return 1 / this.mainTRC },
// sRGB coefficients
sRco: 0.2126729,
sGco: 0.7151522,
sBco: 0.0721750,
// G-4g constants for use with 2.4 exponent
normBG: 0.56,
normTXT: 0.57,
revTXT: 0.62,
revBG: 0.65,
// G-4g Clamps and Scalers
blkThrs: 0.022,
blkClmp: 1.414,
scaleBoW: 1.14,
scaleWoB: 1.14,
loBoWoffset: 0.027,
loWoBoffset: 0.027,
deltaYmin: 0.0005,
loClip: 0.1,
///// MAGIC NUMBERS for UNCLAMP, for use with 0.022 & 1.414 /////
// Magic Numbers for reverseAPCA
mFactor: 1.94685544331710,
get mFactInv() { return 1 / this.mFactor},
mOffsetIn: 0.03873938165714010,
mExpAdj: 0.2833433964208690,
get mExp() { return this.mExpAdj / this.blkClmp},
mOffsetOut: 0.3128657958707580,
}
//////////////////////////////////////////////////////////////////////////////
////////// APCA CALCULATION FUNCTIONS \/////////////////////////////////////
////////// ƒ APCAcontrast() ////////////////////////////////////////////
export function APCAcontrast (txtY,bgY,places = -1) {

@@ -145,3 +201,4 @@ // send linear Y (luminance) for text and background.

if(isNaN(txtY)||isNaN(bgY)||Math.min(txtY,bgY)<icp[0]||Math.max(txtY,bgY)>icp[1]){
if(isNaN(txtY)||isNaN(bgY)||Math.min(txtY,bgY)<icp[0]||
Math.max(txtY,bgY)>icp[1]){
return 0.0; // return zero on error

@@ -151,18 +208,2 @@ // return 'error'; // optional string return for error

////////// APCA 0.1.4 G - 4g - W3 Constants ///////////////////////
const normBG = 0.56,
normTXT = 0.57,
revTXT = 0.62,
revBG = 0.65; // G-4g constants for use with 2.4 exponent
const blkThrs = 0.022,
blkClmp = 1.414,
scaleBoW = 1.14,
scaleWoB = 1.14,
loBoWoffset = 0.027,
loWoBoffset = 0.027,
loClip = 0.1,
deltaYmin = 0.0005;
////////// SAPC LOCAL VARS /////////////////////////////////////////

@@ -172,3 +213,3 @@

let outputContrast = 0.0; // For weighted final values
let polCat = 'BoW'; // Alternate Polarity Indicator. N normal R reverse
let polCat = 'BoW'; // Alternate Polarity Indicator. N normal R reverse

@@ -189,9 +230,9 @@ // TUTORIAL

// Soft clamps Y for either color if it is near black.
txtY = (txtY > blkThrs) ? txtY :
txtY + Math.pow(blkThrs - txtY, blkClmp);
bgY = (bgY > blkThrs) ? bgY :
bgY + Math.pow(blkThrs - bgY, blkClmp);
txtY = (txtY > SA98G.blkThrs) ? txtY :
txtY + Math.pow(SA98G.blkThrs - txtY, SA98G.blkClmp);
bgY = (bgY > SA98G.blkThrs) ? bgY :
bgY + Math.pow(SA98G.blkThrs - bgY, SA98G.blkClmp);
///// Return 0 Early for extremely low ∆Y
if ( Math.abs(bgY - txtY) < deltaYmin ) { return 0.0; }
if ( Math.abs(bgY - txtY) < SA98G.deltaYmin ) { return 0.0; }

@@ -203,8 +244,9 @@

// Calculate the SAPC contrast value and scale
SAPC = ( Math.pow(bgY, normBG) - Math.pow(txtY, normTXT) ) * scaleBoW;
// Calculate the SAPC contrast value and scale
SAPC = ( Math.pow(bgY, SA98G.normBG) -
Math.pow(txtY, SA98G.normTXT) ) * SA98G.scaleBoW;
// Low Contrast smooth rollout to prevent polarity reversal
// and also a low-clip for very low contrasts
outputContrast = (SAPC < loClip) ? 0.0 : SAPC - loBoWoffset;
outputContrast = (SAPC < SA98G.loClip) ? 0.0 : SAPC - SA98G.loBoWoffset;

@@ -215,5 +257,6 @@ } else { // For reverse polarity, light text on dark (WoB)

SAPC = ( Math.pow(bgY, revBG) - Math.pow(txtY, revTXT) ) * scaleWoB;
SAPC = ( Math.pow(bgY, SA98G.revBG) -
Math.pow(txtY, SA98G.revTXT) ) * SA98G.scaleWoB;
outputContrast = (SAPC > -loClip) ? 0.0 : SAPC + loWoBoffset;
outputContrast = (SAPC > -SA98G.loClip) ? 0.0 : SAPC + SA98G.loWoBoffset;
}

@@ -239,46 +282,52 @@

////////// ƒ findBg() //////////////////////////////////////////////////
export function reverseAPCA (contrast = 0,knownY = 1.0,knownType = 'bg',returnAs = 'hex') {
if (Math.abs(contrast) < 5) { return false }; // abs contrast must be > 5
/* SWITCH -- WORK IN PROGRESS DO NOT USE
////////// ƒ invertAPCA() //////////////////////////////////////////////////
export function invertAPCA (
{knownColor: [128,128,128], knownType: 'bg', targetCnst: 75,
returnAs: 'object', unknownType: 'txt', hueInvert: false,
hueRange: 5, preserveSat: false }) {
//if (Math.abs(targetCnst) < 15) { return false }; // abs contrast must be > 15
let knownY = sRGBtoY (knownColor);
let unknownY = knownY, knownExp, unknownExp;
const mainTRCencode = 1/2.4,
normBG = 0.56,
normTXT = 0.57,
revTXT = 0.62,
revBG = 0.65; // G-4g constants for use with 2.4 exponent
let min,max,knownLs,isBG = true;
const blkThrs = 0.022,
blkClmp = 1.414,
scale = 1.14,
offset = contrast > 0 ? 0.027 : -0.027;
///// MAGIC NUMBERS for UNCLAMP, for use with 0.022 & 1.414 /////
const mFactor = 1.94685544331710;
const mFactInv = 1/mFactor;
const mOffsetIn = 0.03873938165714010;
const mExpAdj = 0.2833433964208690;
const mExp = mExpAdj / blkClmp;
const mOffsetOut = 0.3128657958707580;
if (knownType == 'bg' || knownType == 'background') {
knownLs = Math.pow(knownY, );
black = APCAcontrast(0,knownY);
white = APCAcontrast(1,knownY);
} else if (knownType == 'txt' || knownType == 'text') {
isBG = false;
black = APCAcontrast(knownY,0);
white = APCAcontrast(knownY,1);
} else { return false } // return false on error
contrast = ( parseFloat(contrast) * 0.01 + offset ) / scale;
///// APCA 0.0.98G - 4g - W3 Compatible Constants ////////////////////
const scale = contrast > 0 ? SA98G.scaleBoW : SA98G.scaleWoB;
const offset = contrast > 0 ? SA98G.loBoWoffset : -SA98G.loWoBoffset;
targetCnst = ( parseFloat(targetCnst) * 0.01 + offset ) / scale;
// Soft clamps Y if it is near black.
knownY = (knownY > blkThrs) ? knownY :
knownY + Math.pow(blkThrs - knownY, blkClmp);
knownY = (knownY > SA98G.blkThrs) ? knownY :
knownY + Math.pow(SA98G.blkThrs - knownY, SA98G.blkClmp);
// set the known and unknown exponents
if (knownType == 'bg' || knownType == 'background') {
knownExp = contrast > 0 ? normBG : revBG;
unknownExp = contrast > 0 ? normTXT : revTXT;
unknownY = Math.pow( Math.pow(knownY,knownExp) - contrast, 1/unknownExp );
if (isBG) {
knownExp = targetCnst > 0 ? SA98G.normBG : SA98G.revBG;
unknownExp = targetCnst > 0 ? SA98G.normTXT : SA98G.revTXT;
unknownY = Math.pow( Math.pow(knownY,knownExp) - targetCnst, 1/unknownExp );
if (isNaN(unknownY)) return false;
} else if (knownType == 'txt' || knownType == 'text') {
knownExp = contrast > 0 ? normTXT : revTXT;
unknownExp = contrast > 0 ? normBG : revBG;
unknownY = Math.pow(contrast + Math.pow(knownY,knownExp), 1/unknownExp );
} else if (!isBG) {
knownExp = targetCnst > 0 ? SA98G.normTXT : SA98G.revTXT;
unknownExp = targetCnst > 0 ? SA98G.normBG : SA98G.revBG;
unknownY = Math.pow(targetCnst + Math.pow(knownY,knownExp), 1/unknownExp );
if (isNaN(unknownY)) return false;
} else { return false } // return false on error
}

@@ -292,4 +341,5 @@ //return contrast +'----'+unknownY;

// unclamp
unknownY = (unknownY > blkThrs) ? unknownY :
(Math.pow(((unknownY + mOffsetIn) * mFactor), mExp) * mFactInv) - mOffsetOut;
unknownY = (unknownY > SA98G.blkThrs) ? unknownY :
(Math.pow(((unknownY + SA98G.mOffsetIn)m* SA98G.mFactor),
SA98G.mExp) * SA98G.mFactInv) - SA98G.mOffsetOut;

@@ -300,9 +350,16 @@ // unknownY - 0.22 * Math.pow(unknownY*0.5, 1/blkClmp);

if (returnAs === 'hex') {
let hexB = ( Math.round(Math.pow(unknownY,mainTRCencode) * 255)
let testedCnst = (isBG) ? APCAcontrast(unknownY,knownY) :
APCAcontrast(knownY,unknownY);
if (returnAs === 'object') {
let hexB = ( Math.round(Math.pow(unknownY,SA98G.mainTRCencode) * 255)
).toString(16).padStart(2,'0');
hexB = '#' + hexB + hexB + hexB;
return {color: hexB, Lc: testedCnst, whiteLc: white, blackLc: black};
} else if (returnAs === 'hex') {
let hexB = ( Math.round(Math.pow(unknownY,SA98G.mainTRCencode) * 255)
).toString(16).padStart(2,'0');
return '#' + hexB + hexB + hexB;
} else if (returnAs === 'color') {
let colorB = Math.round(Math.pow(unknownY,mainTRCencode) * 255);
} else if (returnAs === 'array') {
let colorB = Math.round(Math.pow(unknownY,SA98G.mainTRCencode) * 255);
let retUse = (knownType == 'bg') ? 'txtColor' : 'bgColor'

@@ -314,129 +371,75 @@ return [colorB,colorB,colorB,1,retUse];

}
// */ // END SWITCH
////////// ƒ sRGBtoY() //////////////////////////////////////////////////
export function sRGBtoY (rgb = [0,0,0]) { // send sRGB 8bpc (0xFFFFFF) or string
// NOTE: Currently expects 0-255
///// APCA 0.1.4 G - 4g - W3 Constants ////////////////////////
const mainTRC = 2.4; // 2.4 exponent emulates actual monitor perception
////////// ƒ reverseAPCA() DEPRECATED SOON ///////////////////////////////
export function reverseAPCA (contrast = 0,knownY = 1.0,
knownType = 'bg',returnAs = 'hex') {
const sRco = 0.2126729,
sGco = 0.7151522,
sBco = 0.0721750; // sRGB coefficients
// Future:
// 0.2126478133913640 0.7151791475336150 0.0721730390750208
// Derived from:
// xW yW K xR yR xG yG xB yB
// 0.312720 0.329030 6504 0.640 0.330 0.300 0.600 0.150 0.060
if (Math.abs(contrast) < 9) { return false }; // abs contrast must be > 9
let unknownY = knownY, knownExp, unknownExp;
///// APCA 0.0.98G - 4g - W3 Compatible Constants ////////////////////
// linearize r, g, or b then apply coefficients
// and sum then return the resulting luminance
const scale = contrast > 0 ? SA98G.scaleBoW : SA98G.scaleWoB;
const offset = contrast > 0 ? SA98G.loBoWoffset : -SA98G.loWoBoffset;
function simpleExp (chan) { return Math.pow(chan/255.0, mainTRC); };
return sRco * simpleExp(rgb[0]) +
sGco * simpleExp(rgb[1]) +
sBco * simpleExp(rgb[2]);
} // End sRGBtoY()
contrast = ( parseFloat(contrast) * 0.01 + offset ) / scale;
// Soft clamps Y if it is near black.
knownY = (knownY > SA98G.blkThrs) ? knownY :
knownY + Math.pow(SA98G.blkThrs - knownY, SA98G.blkClmp);
// set the known and unknown exponents
if (knownType == 'bg' || knownType == 'background') {
knownExp = contrast > 0 ? SA98G.normBG : SA98G.revBG;
unknownExp = contrast > 0 ? SA98G.normTXT : SA98G.revTXT;
unknownY = Math.pow( Math.pow(knownY,knownExp) - contrast, 1/unknownExp );
if (isNaN(unknownY)) return false;
} else if (knownType == 'txt' || knownType == 'text') {
knownExp = contrast > 0 ? SA98G.normTXT : SA98G.revTXT;
unknownExp = contrast > 0 ? SA98G.normBG : SA98G.revBG;
unknownY = Math.pow(contrast + Math.pow(knownY,knownExp), 1/unknownExp );
if (isNaN(unknownY)) return false;
} else { return false } // return false on error
//return contrast +'----'+unknownY;
if (unknownY > 1.06 || unknownY < 0) { return false } // return false on overflow
// if (unknownY < 0) { return false } // return false on underflow
//unknownY = Math.max(unknownY,0.0);
// unclamp
unknownY = (unknownY > SA98G.blkThrs) ? unknownY :
(Math.pow(((unknownY + SA98G.mOffsetIn) * SA98G.mFactor),
SA98G.mExp) * SA98G.mFactInv) - SA98G.mOffsetOut;
// unknownY - 0.22 * Math.pow(unknownY*0.5, 1/blkClmp);
unknownY = Math.max(Math.min(unknownY,1.0),0.0);
if (returnAs === 'hex') {
let hexB = ( Math.round(Math.pow(unknownY,SA98G.mainTRCencode) * 255)
).toString(16).padStart(2,'0');
////////// ƒ displayP3toY() /////////////////////////////////////////////
export function displayP3toY (rgb = [0,0,0]) { // send rgba array
return '#' + hexB + hexB + hexB;
} else if (returnAs === 'color') {
let colorB = Math.round(Math.pow(unknownY,SA98G.mainTRCencode) * 255);
let retUse = (knownType == 'bg') ? 'txtColor' : 'bgColor'
return [colorB,colorB,colorB,1,retUse];
} else if (returnAs === 'Y' || returnAs === 'y') {
return Math.max(0.0,unknownY);
} else { return false } // return knownY on error
}
// NOTE: Currently Apple has the tuple as 0.0 to 1.0, NOT 255
///// APCA 0.1.4 G - 4g - W3 Constants ////////////////////////
const mainTRC = 2.4; // 2.4 exponent emulates actual monitor perception
// Pending evaluation, because, Apple...
const sRco = 0.2289829594805780,
sGco = 0.6917492625852380,
sBco = 0.0792677779341829; // displayP3 coefficients
// Derived from:
// xW yW K xR yR xG yG xB yB
// 0.312720 0.329030 6504 0.680 0.320 0.265 0.690 0.150 0.060
////////// ƒ calcAPCA() /////////////////////////////////////////////
export function calcAPCA (textColor, bgColor, places = -1, round = true) {
// linearize r, g, or b then apply coefficients
// and sum then return the resulting luminance
function simpleExp (chan) { return Math.pow(chan, mainTRC); };
return sRco * simpleExp(rgb[0]) +
sGco * simpleExp(rgb[1]) +
sBco * simpleExp(rgb[2]);
} // End displayP3toY()
////////// ƒ adobeRGBtoY() /////////////////////////////////////////////
export function adobeRGBtoY (rgb = [0,0,0]) { // send rgba array
// NOTE: Currently expects 0-255
///// APCA 0.1.4 G - 4g - W3 Constants ////////////////////////
const mainTRC = 2.35; // 2.35 exponent emulates actual monitor perception
// Pending evaluation...
const sRco = 0.2973550227113810,
sGco = 0.6273727497145280,
sBco = 0.0752722275740913; // adobeRGB coefficients
// Derived from:
// xW yW K xR yR xG yG xB yB
// 0.312720 0.329030 6504 0.640 0.330 0.210 0.710 0.150 0.060
// linearize r, g, or b then apply coefficients
// and sum then return the resulting luminance
function simpleExp (chan) { return Math.pow(chan/255.0, mainTRC); };
return sRco * simpleExp(rgb[0]) +
sGco * simpleExp(rgb[1]) +
sBco * simpleExp(rgb[2]);
} // End displayP3toY()
////////// ƒ alphaBlend() /////////////////////////////////////////////
// send rgba array for top, rgb for bottom.
// Only foreground has alpha of 0.0 to 1.0
// This blends using gamma encoded space (standard)
// rounded 0-255 or set isInt false for float 0.0-1.0
export function alphaBlend (rgbaFG=[0,0,0,1.0], rgbBG=[0,0,0], round = true ) {
rgbaFG[3] = Math.max(Math.min(rgbaFG[3], 1.0), 0.0); // clamp alpha
let compBlend = 1.0 - rgbaFG[3];
let rgbOut = [0,0,0,1,true]; // or just use rgbBG to retain other elements?
for (let i=0;i<3;i++) {
rgbOut[i] = rgbBG[i] * compBlend + rgbaFG[i] * rgbaFG[3];
if (round) rgbOut[i] = Math.min(Math.round(rgbOut[i]),255);
};
return rgbOut;
} // End alphaBlend()
////////// ƒ calcAPCA() /////////////////////////////////////////////
export function calcAPCA (textColor, bgColor, places = -1, isInt = true) {
// Note that this function requires colorParsley !!

@@ -447,4 +450,4 @@ let bgClr = colorParsley(bgColor);

if (hasAlpha) { txClr = alphaBlend( txClr, bgClr, isInt); };
if (hasAlpha) { txClr = alphaBlend( txClr, bgClr, round); };
return APCAcontrast( sRGBtoY(txClr), sRGBtoY(bgClr), places)

@@ -456,36 +459,11 @@ } // End calcAPCA()

///////////////////////////////////////////////////////////////////////////////
////////// ƒ fontLookupAPCA() 0.1.7 (G) //////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
////////// ƒ fontLookupAPCA() 0.1.7 (G) \////////////////////////////////
///////// \//////////////////////////////
export function fontLookupAPCA (contrast,places=3) {
export function fontLookupAPCA (contrast,places=2) {
// APCA CONTRAST FONT LOOKUP TABLES
// Copyright © 2022 by Myndex Research and Andrew Somers. All Rights Reserved
// Public Beta 0.1.7 (G) • MAY 28 2022
// For the following arrays, the Y axis is contrastArrayLen
// The two x axis are weightArrayLen and scoreArrayLen
////////////////////////////////////////////////////////////////////////////
///// CONTRAST * FONT WEIGHT & SIZE /////////////////////////////////////
// MAY 28 2022
const contrastArrayAscend = ['lc',0,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,];
const contrastArrayLenAsc = contrastArrayAscend.length; // Y azis
const weightArray = [0,100,200,300,400,500,600,700,800,900];
const weightArrayLen = weightArray.length; // X axis
let returnArray = [contrast.toFixed(places),0,0,0,0,0,0,0,0,0,];
const returnArrayLen = returnArray.length; // X axis
//// Lc 45 * 0.2 = 9, and 9 is the index for the row for Lc 45
contrast = Math.abs(contrast);
const factor = 0.2; // 1/5
let index = (contrast * factor) | 0 ; // n|0 is bw floor
///////////////////////////////////////////////////////////////////////////////
///// CONTRAST * FONT WEIGHT & SIZE //////////////////////////////////////
// Font size interpolations. Here the chart was re-ordered to put

@@ -554,3 +532,3 @@ // the main contrast levels each on one line, instead of font size per line.

// DELTA - MAIN FONT LOOKUP May 28 2022 EXPANDED
// EXPANDED Sorted by Lc Value •• DELTA
// EXPANDED Sorted by Lc Value •• DELTA
// The pre-calculated deltas of the above array

@@ -587,15 +565,38 @@

///////////////////////////////////////////////////////////////////////////
///////// Font and Score Interpolation \////////////////////////////////
// APCA CONTRAST FONT LOOKUP TABLES
// Copyright © 2022 by Myndex Research and Andrew Somers. All Rights Reserved
// Public Beta 0.1.7 (G) • MAY 28 2022
// For the following arrays, the Y axis is contrastArrayLen
// The two x axis are weightArrayLen and scoreArrayLen
// MAY 28 2022
const weightArray = [0,100,200,300,400,500,600,700,800,900];
const weightArrayLen = weightArray.length; // X axis
let returnArray = [contrast.toFixed(places),0,0,0,0,0,0,0,0,0,];
const returnArrayLen = returnArray.length; // X axis
const contrastArrayAscend = ['lc',0,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,];
const contrastArrayLenAsc = contrastArrayAscend.length; // Y azis
//// Lc 45 * 0.2 = 9, and 9 is the index for the row for Lc 45
let tempFont = 777;
let scoreAdj = 0.1;
let w = 0;
contrast = Math.abs(contrast); // Polarity unneeded for LUT
const factor = 0.2; // 1/5 as LUT is in increments of 5
const index = (contrast == 0) ?
1 : (contrast * factor) | 0 ; // LUT row... n|0 is bw floor
let w = 0;
// scoreAdj interpolates the needed font side per the Lc
let scoreAdj = (contrast - fontMatrixAscend[index][w]) * factor;
// populate returnArray with interpolated values
w++; // determines column in font matrix LUT
// returnArray[w] = contrast;
scoreAdj = (contrast - fontMatrixAscend[index][w]) * factor;
w++;
///////// Font and Score Interpolation \/////////////////////////////////
// populate returnArray with interpolated values
for (; w < weightArrayLen; w++) {

@@ -605,29 +606,164 @@

if (tempFont > 400) {
if (tempFont > 400) { // declares a specific minimum for the weight.
returnArray[w] = tempFont;
} else if (contrast < 14.0 ) {
returnArray[w] = 999;
} else if (contrast < 29.0 ) {
returnArray[w] = 777;
} else if (contrast < 14.5 ) {
returnArray[w] = 999; // 999 = do not use for anything
} else if (contrast < 29.5 ) {
returnArray[w] = 777; // 777 = non-text only
} else {
// INTERPOLATION OF FONT SIZE
// sets level for 0.5 size increments of smaller fonts
// sets level for 0.5px size increments of smaller fonts
// Note bitwise (n|0) instead of floor
(tempFont > 24) ?
returnArray[w] =
returnArray[w] =
Math.round(tempFont - (fontDeltaAscend[index][w] * scoreAdj)) :
returnArray[w] =
returnArray[w] =
tempFont - ((2.0 * fontDeltaAscend[index][w] * scoreAdj) | 0) * 0.5;
// (n|0) is bw floor
// (n|0) is bitwise floor
}
}
/////////\ End Interpolation ////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
return returnArray
}
} // end fontLookupAPCA
/////////\ ///////////////////////////\
//////////\ END fontLookupAPCA() 0.1.7 (G) /////////////////////////////\
/////////////////////////////////////////////////////////////////////////////\
////\ //////////////////////////////////////////
/////\ END APCA 0.1.4 G-4g BLOCK //////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
////////// LUMINANCE CONVERTERS |//////////////////////////////////////////
////////// ƒ sRGBtoY() //////////////////////////////////////////////////
export function sRGBtoY (rgb = [0,0,0]) { // send sRGB 8bpc (0xFFFFFF) or string
// NOTE: Currently expects 0-255
///// APCA 0.0.98G - 4g - W3 Compatible Constants ////////////////////
/*
const mainTRC = 2.4; // 2.4 exponent emulates actual monitor perception
const sRco = 0.2126729,
sGco = 0.7151522,
sBco = 0.0721750; // sRGB coefficients
*/
// Future:
// 0.2126478133913640 0.7151791475336150 0.0721730390750208
// Derived from:
// xW yW K xR yR xG yG xB yB
// 0.312720 0.329030 6504 0.640 0.330 0.300 0.600 0.150 0.060
// linearize r, g, or b then apply coefficients
// and sum then return the resulting luminance
function simpleExp (chan) { return Math.pow(chan/255.0, SA98G.mainTRC); };
return SA98G.sRco * simpleExp(rgb[0]) +
SA98G.sGco * simpleExp(rgb[1]) +
SA98G.sBco * simpleExp(rgb[2]);
} // End sRGBtoY()
////////// ƒ displayP3toY() /////////////////////////////////////////////
export function displayP3toY (rgb = [0,0,0]) { // send rgba array
// NOTE: Currently Apple has the tuple as 0.0 to 1.0, NOT 255
///// APCA 0.0.98G - 4g - W3 Compatible Constants ////////////////////
const mainTRC = 2.4; // 2.4 exponent emulates actual monitor perception
// Pending evaluation, because, Apple...
const sRco = 0.2289829594805780,
sGco = 0.6917492625852380,
sBco = 0.0792677779341829; // displayP3 coefficients
// Derived from:
// xW yW K xR yR xG yG xB yB
// 0.312720 0.329030 6504 0.680 0.320 0.265 0.690 0.150 0.060
// linearize r, g, or b then apply coefficients
// and sum then return the resulting luminance
function simpleExp (chan) { return Math.pow(chan, mainTRC); };
return sRco * simpleExp(rgb[0]) +
sGco * simpleExp(rgb[1]) +
sBco * simpleExp(rgb[2]);
} // End displayP3toY()
////////// ƒ adobeRGBtoY() /////////////////////////////////////////////
export function adobeRGBtoY (rgb = [0,0,0]) { // send rgba array
// NOTE: Currently expects 0-255
///// APCA 0.0.98G - 4g - W3 Compatible Constants ////////////////////
const mainTRC = 2.35; // 2.35 exponent emulates actual monitor perception
// Pending evaluation...
const sRco = 0.2973550227113810,
sGco = 0.6273727497145280,
sBco = 0.0752722275740913; // adobeRGB coefficients
// Derived from:
// xW yW K xR yR xG yG xB yB
// 0.312720 0.329030 6504 0.640 0.330 0.210 0.710 0.150 0.060
// linearize r, g, or b then apply coefficients
// and sum then return the resulting luminance
function simpleExp (chan) { return Math.pow(chan/255.0, mainTRC); };
return sRco * simpleExp(rgb[0]) +
sGco * simpleExp(rgb[1]) +
sBco * simpleExp(rgb[2]);
} // End displayP3toY()
////////////////////////////////////////////////////////////////////////////
////////// UTILITIES \///////////////////////////////////////////////////
////////// ƒ alphaBlend() /////////////////////////////////////////////
// send rgba array for text/icon, rgb for background.
// Only foreground allows alpha of 0.0 to 1.0
// This blends using gamma encoded space (standard)
// rounded 0-255 or set round=false for number 0.0-255.0
export function alphaBlend (rgbaFG=[0,0,0,1.0], rgbBG=[0,0,0], round = true ) {
rgbaFG[3] = Math.max(Math.min(rgbaFG[3], 1.0), 0.0); // clamp alpha 0-1
let compBlend = 1.0 - rgbaFG[3];
let rgbOut = [0,0,0,1,true]; // or just use rgbBG to retain other elements?
for (let i=0;i<3;i++) {
rgbOut[i] = rgbBG[i] * compBlend + rgbaFG[i] * rgbaFG[3];
if (round) rgbOut[i] = Math.min(Math.round(rgbOut[i]),255);
};
return rgbOut;
} // End alphaBlend()
//\ ////////////////////////////////////////
///\ ////////////////////////////////////////
////\ ////////////////////////////////////////
/////\ END APCA 0.1.8 G-4g BLOCK ////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

@@ -0,1 +1,3 @@

// APCA Test Script for 0.1.7
import test from 'ava';

@@ -2,0 +4,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc