Skip to content

Commit

Permalink
chore: align remaining context types and descriptions
Browse files Browse the repository at this point in the history
  • Loading branch information
davidenke committed Sep 14, 2024
1 parent fb5321e commit acbd68a
Show file tree
Hide file tree
Showing 20 changed files with 51 additions and 36 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

Examples: https://davidenke.github.io/context-filter-polyfill/

Polyfills [`CanvasRenderingContext2d.filter`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter) capability of adopting CSS3 filters to canvas contexts at least partially.
Polyfills [`CanvasRenderingContext2d`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) and [`OffscreenCanvasRenderingContext2d`](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvasRenderingContext2d) capability of adopting [CSS3 filters](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter) on canvas contexts (at least partially).

Right now ~~only WebKit [misses an implementation (Bugzilla #198416)](https://bugs.webkit.org/show_bug.cgi?id=198416)~~ all engines support it natively, despite Safari not having shipped it yet in the stable release channel.

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "context-filter-polyfill",
"version": "0.3.17",
"description": "Polyfills `CanvasRenderingContext2d.prototype.filter` capability of adopting CSS3 filters to canvas contexts at least partially.",
"description": "Polyfills the `CanvasRenderingContext2d` and `OffscreenCanvasRenderingContext2D` capability of adopting CSS3 filters on canvas contexts (at least partially).",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
11 changes: 4 additions & 7 deletions src/example.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
<h1>context-filter-polyfill</h1>
<p>
Polyfills
<code>CanvasRenderingContext2d.prototype.filter</code> capability of
adopting CSS3 filters to canvas contexts at least partially.
<code>CanvasRenderingContext2d.prototype.filter</code> and
<code>OffscreenCanvasRenderingContext2D.prototype.filter</code>
capability of adopting CSS3 filters to canvas contexts at least
partially.
</p>
<p>
Right now
Expand All @@ -35,11 +37,6 @@ <h1>context-filter-polyfill</h1>
<p>
This example will show the polyfilled filters on the left and the
untouched native implementation on the right.
<em
>Thus, <strong>no difference</strong> can be seen on
<strong>WebKit</strong>-based browsers, which are polyfilled either
way.</em
>
</p>
<p>
So in this case here, you're using <em data-debug="browser"></em>, which
Expand Down
12 changes: 9 additions & 3 deletions src/example.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { supportsContextFilters } from './utils/detection.utils';

function detectBrowser() {
const ua = navigator.userAgent;
if (ua.includes('Edg')) {
Expand All @@ -14,8 +16,9 @@ function detectBrowser() {

return 'as unknown browser';
}

function isPolyfilled() {
return 'filter' in CanvasRenderingContext2D.prototype ? 'is not' : 'is';
return supportsContextFilters() ? 'is not' : 'is';
}

document.querySelector('[data-debug="browser"]')!.textContent = detectBrowser();
Expand All @@ -29,7 +32,10 @@ document.querySelector('iframe')!.srcdoc = document
let cloned = 0;
window.addEventListener('context-filter-polyfill:draw', ({ detail }) => {
const { original, clone, drawFn, drawArgs } = detail;
if (original.canvas.parentElement?.classList.contains('debug')) {
if (
'parentElement' in original.canvas &&
original.canvas.parentElement?.classList.contains('debug')
) {
++cloned;
const wrapper = document.createElement('div');
wrapper.classList.add('clone');
Expand All @@ -39,7 +45,7 @@ window.addEventListener('context-filter-polyfill:draw', ({ detail }) => {
label.textContent = `${drawFn}(${drawArgs.map(String).join(', ')})`;

wrapper.appendChild(label);
wrapper.appendChild(clone.canvas);
wrapper.appendChild(clone.canvas as HTMLCanvasElement);
document.getElementById('clones')?.appendChild(wrapper);
}
});
3 changes: 2 additions & 1 deletion src/filters/blur.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { blur } from './blur.filter.js';

describe('filters/blur', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/brightness.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { brightness } from './brightness.filter.js';

describe('filters/brightness', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/contrast.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { contrast } from './contrast.filter.js';

describe('filters/contrast', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/grayscale.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { grayscale } from './grayscale.filter.js';

describe('filters/grayscale', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/hue-rotate.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { hueRotate } from './hue-rotate.filter.js';

describe('filters/hue-rotate', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/invert.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { invert } from './invert.filter.js';

describe('filters/invert', () => {
const size = 30;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/none.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { none } from './none.filter.js';

describe('filters/none', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/opacity.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { opacity } from './opacity.filter.js';

describe('filters/opacity', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/saturate.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { saturate } from './saturate.filter.js';

describe('filters/saturate', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/filters/sepia.filter.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { expect } from '@esm-bundle/chai';

import { imageDataMock } from '../mocks/mock.data.js';
import type { Context2D } from '../utils/proxy.utils.js';
import { sepia } from './sepia.filter.js';

describe('filters/sepia', () => {
let width: number;
let height: number;
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
6 changes: 3 additions & 3 deletions src/polyfill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import './filters/saturate.filter.js';
import './filters/sepia.filter.js';

import { applyFilter } from './utils/filter.utils.js';
import { applyProxy } from './utils/proxy.utils.js';
import { applyProxy, type Context2D } from './utils/proxy.utils.js';

declare global {
interface WindowEventMap {
'context-filter-polyfill:draw': CustomEvent<{
original: CanvasRenderingContext2D;
clone: CanvasRenderingContext2D;
original: Context2D;
clone: Context2D;
drawFn: string;
drawArgs: unknown[];
}>;
Expand Down
6 changes: 4 additions & 2 deletions src/types/filter.type.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { Context2D } from '../utils/proxy.utils';

export type Filter = (
context: CanvasRenderingContext2D,
context: Context2D,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...options: any[]
) => CanvasRenderingContext2D;
) => Context2D;
7 changes: 4 additions & 3 deletions src/utils/context.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ declare global {
[P in keyof T as T[P] extends Value | undefined ? P : never]: T[P];
};

// convenience type for making all properties writeable
type Writeable<T> = { -readonly [P in keyof T]: T[P] };

// all callable functions in CanvasRenderingContext2D
// all callable functions in 2d contexts
type Context2DFn = PickByType<
Context2D,
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
Expand All @@ -35,7 +36,7 @@ declare global {
}
}

// a list of all drawing functions in CanvasRenderingContext2D
// a list of all drawing functions in 2d contexts
export const DRAWING_FN_PROPS = [
'clearRect',
'clip',
Expand All @@ -49,7 +50,7 @@ export const DRAWING_FN_PROPS = [
'strokeText',
'reset',
'restore',
] as const satisfies Partial<Array<keyof CanvasRenderingContext2D>>;
] as const satisfies Partial<Array<keyof Context2D>>;

export function isDrawingFn(
property: string,
Expand Down
2 changes: 1 addition & 1 deletion src/utils/filter.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ chai.use(sinonChai);
describe('utils/filter.utils', () => {
describe('applyFilter', () => {
let canvas: HTMLCanvasElement;
let context: CanvasRenderingContext2D;
let context: Context2D;

beforeEach(() => {
canvas = document.createElement('canvas');
Expand Down
3 changes: 2 additions & 1 deletion src/utils/filter.utils.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { SUPPORTED_FILTERS } from '../globals/supported-filters.global.js';
import type { Context2D } from './proxy.utils.js';

// applies the given filter to the provided canvas 2d context
export const applyFilter = (
context: CanvasRenderingContext2D,
context: Context2D,
canvasFilters: CanvasFilters['filter'] = 'none',
) => {
// parse applied filters and call implementations
Expand Down
6 changes: 2 additions & 4 deletions src/utils/history.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Context2D } from './proxy.utils';

export type Context2DHistoryEntry = {
type: 'set' | 'apply' | 'draw';
prop: keyof CanvasRenderingContext2D;
prop: keyof Context2D;
value?: unknown;
args?: unknown[];
};
Expand All @@ -23,9 +23,7 @@ export class Context2DHistory extends Set<Context2DHistoryEntry> {
});
}

lastValueOf(
prop: keyof CanvasRenderingContext2D,
): Context2DHistoryEntry | undefined {
lastValueOf(prop: keyof Context2D): Context2DHistoryEntry | undefined {
return [...this].findLast(entry => entry.prop === prop);
}
}

0 comments on commit acbd68a

Please sign in to comment.