UNPKG

fabric

Version:

Object model for HTML5 canvas, and SVG-to-canvas parser. Backed by jsdom and node-canvas.

1 lines 20.3 kB
{"version":3,"file":"BaseFilter.min.mjs","sources":["../../../src/filters/BaseFilter.ts"],"sourcesContent":["import { getEnv } from '../env';\nimport type {\n T2DPipelineState,\n TWebGLAttributeLocationMap,\n TWebGLPipelineState,\n TWebGLProgramCacheItem,\n TWebGLUniformLocationMap,\n} from './typedefs';\nimport { isWebGLPipelineState } from './utils';\nimport {\n highPsourceCode,\n identityFragmentShader,\n vertexSource,\n} from './shaders/baseFilter';\nimport type { Abortable } from '../typedefs';\nimport { FabricError } from '../util/internals/console';\nimport { createCanvasElementFor } from '../util/misc/dom';\n\nconst regex = new RegExp(highPsourceCode, 'g');\n\nexport class BaseFilter<\n Name extends string,\n OwnProps extends Record<string, any> = object,\n SerializedProps extends Record<string, any> = OwnProps,\n> {\n /**\n * Filter type\n * @param {String} type\n * @default\n */\n get type(): Name {\n return (this.constructor as typeof BaseFilter).type as Name;\n }\n\n /**\n * The class type. Used to identify which class this is.\n * This is used for serialization purposes and internally it can be used\n * to identify classes. As a developer you could use `instance of Class`\n * but to avoid importing all the code and blocking tree shaking we try\n * to avoid doing that.\n */\n static type = 'BaseFilter';\n\n /**\n * Contains the uniform locations for the fragment shader.\n * uStepW and uStepH are handled by the BaseFilter, each filter class\n * needs to specify all the one that are needed\n */\n static uniformLocations: string[] = [];\n\n declare static defaults: Record<string, unknown>;\n\n /**\n * Constructor\n * @param {Object} [options] Options object\n */\n constructor({\n type,\n ...options\n }: { type?: never } & Partial<OwnProps> & Record<string, any> = {}) {\n Object.assign(\n this,\n (this.constructor as typeof BaseFilter).defaults,\n options,\n );\n }\n\n protected getFragmentSource(): string {\n return identityFragmentShader;\n }\n\n getVertexSource(): string {\n return vertexSource;\n }\n\n /**\n * Compile this filter's shader program.\n *\n * @param {WebGLRenderingContext} gl The GL canvas context to use for shader compilation.\n * @param {String} fragmentSource fragmentShader source for compilation\n * @param {String} vertexSource vertexShader source for compilation\n */\n createProgram(\n gl: WebGLRenderingContext,\n fragmentSource: string = this.getFragmentSource(),\n vertexSource: string = this.getVertexSource(),\n ) {\n const {\n WebGLProbe: { GLPrecision = 'highp' },\n } = getEnv();\n if (GLPrecision !== 'highp') {\n fragmentSource = fragmentSource.replace(\n regex,\n highPsourceCode.replace('highp', GLPrecision),\n );\n }\n const vertexShader = gl.createShader(gl.VERTEX_SHADER);\n const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\n const program = gl.createProgram();\n\n if (!vertexShader || !fragmentShader || !program) {\n throw new FabricError(\n 'Vertex, fragment shader or program creation error',\n );\n }\n gl.shaderSource(vertexShader, vertexSource);\n gl.compileShader(vertexShader);\n if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\n throw new FabricError(\n `Vertex shader compile error for ${this.type}: ${gl.getShaderInfoLog(\n vertexShader,\n )}`,\n );\n }\n\n gl.shaderSource(fragmentShader, fragmentSource);\n gl.compileShader(fragmentShader);\n if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\n throw new FabricError(\n `Fragment shader compile error for ${this.type}: ${gl.getShaderInfoLog(\n fragmentShader,\n )}`,\n );\n }\n\n gl.attachShader(program, vertexShader);\n gl.attachShader(program, fragmentShader);\n gl.linkProgram(program);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n throw new FabricError(\n `Shader link error for \"${this.type}\" ${gl.getProgramInfoLog(program)}`,\n );\n }\n\n const uniformLocations = this.getUniformLocations(gl, program) || {};\n uniformLocations.uStepW = gl.getUniformLocation(program, 'uStepW');\n uniformLocations.uStepH = gl.getUniformLocation(program, 'uStepH');\n\n return {\n program,\n attributeLocations: this.getAttributeLocations(gl, program),\n uniformLocations,\n };\n }\n\n /**\n * Return a map of attribute names to WebGLAttributeLocation objects.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {WebGLShaderProgram} program The shader program from which to take attribute locations.\n * @returns {Object} A map of attribute names to attribute locations.\n */\n getAttributeLocations(\n gl: WebGLRenderingContext,\n program: WebGLProgram,\n ): TWebGLAttributeLocationMap {\n return {\n aPosition: gl.getAttribLocation(program, 'aPosition'),\n };\n }\n\n /**\n * Return a map of uniform names to WebGLUniformLocation objects.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {WebGLShaderProgram} program The shader program from which to take uniform locations.\n * @returns {Object} A map of uniform names to uniform locations.\n */\n getUniformLocations(\n gl: WebGLRenderingContext,\n program: WebGLProgram,\n ): TWebGLUniformLocationMap {\n const locations = (this.constructor as unknown as typeof BaseFilter<string>)\n .uniformLocations;\n\n const uniformLocations: Record<string, WebGLUniformLocation | null> = {};\n for (let i = 0; i < locations.length; i++) {\n uniformLocations[locations[i]] = gl.getUniformLocation(\n program,\n locations[i],\n );\n }\n return uniformLocations;\n }\n\n /**\n * Send attribute data from this filter to its shader program on the GPU.\n *\n * @param {WebGLRenderingContext} gl The canvas context used to compile the shader program.\n * @param {Object} attributeLocations A map of shader attribute names to their locations.\n */\n sendAttributeData(\n gl: WebGLRenderingContext,\n attributeLocations: Record<string, number>,\n aPositionData: Float32Array,\n ) {\n const attributeLocation = attributeLocations.aPosition;\n const buffer = gl.createBuffer();\n gl.bindBuffer(gl.ARRAY_BUFFER, buffer);\n gl.enableVertexAttribArray(attributeLocation);\n gl.vertexAttribPointer(attributeLocation, 2, gl.FLOAT, false, 0, 0);\n gl.bufferData(gl.ARRAY_BUFFER, aPositionData, gl.STATIC_DRAW);\n }\n\n _setupFrameBuffer(options: TWebGLPipelineState) {\n const gl = options.context;\n if (options.passes > 1) {\n const width = options.destinationWidth;\n const height = options.destinationHeight;\n if (options.sourceWidth !== width || options.sourceHeight !== height) {\n gl.deleteTexture(options.targetTexture);\n options.targetTexture = options.filterBackend.createTexture(\n gl,\n width,\n height,\n );\n }\n gl.framebufferTexture2D(\n gl.FRAMEBUFFER,\n gl.COLOR_ATTACHMENT0,\n gl.TEXTURE_2D,\n options.targetTexture,\n 0,\n );\n } else {\n // draw last filter on canvas and not to framebuffer.\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\n gl.finish();\n }\n }\n\n _swapTextures(options: TWebGLPipelineState) {\n options.passes--;\n options.pass++;\n const temp = options.targetTexture;\n options.targetTexture = options.sourceTexture;\n options.sourceTexture = temp;\n }\n\n /**\n * Generic isNeutral implementation for one parameter based filters.\n * Used only in image applyFilters to discard filters that will not have an effect\n * on the image\n * Other filters may need their own version ( ColorMatrix, HueRotation, gamma, ComposedFilter )\n * @param {Object} options\n **/\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n isNeutralState(options?: any): boolean {\n return false;\n }\n\n /**\n * Apply this filter to the input image data provided.\n *\n * Determines whether to use WebGL or Canvas2D based on the options.webgl flag.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyTo(options: TWebGLPipelineState | T2DPipelineState) {\n if (isWebGLPipelineState(options)) {\n this._setupFrameBuffer(options);\n this.applyToWebGL(options);\n this._swapTextures(options);\n } else {\n this.applyTo2d(options);\n }\n }\n\n applyTo2d(_options: T2DPipelineState): void {\n // override by subclass\n }\n\n /**\n * Returns a string that represent the current selected shader code for the filter.\n * Used to force recompilation when parameters change or to retrieve the shader from cache\n * @type string\n **/\n getCacheKey(): string {\n return this.type;\n }\n\n /**\n * Retrieves the cached shader.\n * @param {Object} options\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n * @return {WebGLProgram} the compiled program shader\n */\n retrieveShader(options: TWebGLPipelineState): TWebGLProgramCacheItem {\n const key = this.getCacheKey();\n if (!options.programCache[key]) {\n options.programCache[key] = this.createProgram(options.context);\n }\n return options.programCache[key];\n }\n\n /**\n * Apply this filter using webgl.\n *\n * @param {Object} options\n * @param {Number} options.passes The number of filters remaining to be executed\n * @param {Boolean} options.webgl Whether to use webgl to render the filter.\n * @param {WebGLTexture} options.originalTexture The texture of the original input image.\n * @param {WebGLTexture} options.sourceTexture The texture setup as the source to be filtered.\n * @param {WebGLTexture} options.targetTexture The texture where filtered output should be drawn.\n * @param {WebGLRenderingContext} options.context The GL context used for rendering.\n * @param {Object} options.programCache A map of compiled shader programs, keyed by filter type.\n */\n applyToWebGL(options: TWebGLPipelineState) {\n const gl = options.context;\n const shader = this.retrieveShader(options);\n if (options.pass === 0 && options.originalTexture) {\n gl.bindTexture(gl.TEXTURE_2D, options.originalTexture);\n } else {\n gl.bindTexture(gl.TEXTURE_2D, options.sourceTexture);\n }\n gl.useProgram(shader.program);\n this.sendAttributeData(gl, shader.attributeLocations, options.aPosition);\n\n gl.uniform1f(shader.uniformLocations.uStepW, 1 / options.sourceWidth);\n gl.uniform1f(shader.uniformLocations.uStepH, 1 / options.sourceHeight);\n\n this.sendUniformData(gl, shader.uniformLocations);\n gl.viewport(0, 0, options.destinationWidth, options.destinationHeight);\n gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);\n }\n\n bindAdditionalTexture(\n gl: WebGLRenderingContext,\n texture: WebGLTexture,\n textureUnit: number,\n ) {\n gl.activeTexture(textureUnit);\n gl.bindTexture(gl.TEXTURE_2D, texture);\n // reset active texture to 0 as usual\n gl.activeTexture(gl.TEXTURE0);\n }\n\n unbindAdditionalTexture(gl: WebGLRenderingContext, textureUnit: number) {\n gl.activeTexture(textureUnit);\n gl.bindTexture(gl.TEXTURE_2D, null);\n gl.activeTexture(gl.TEXTURE0);\n }\n\n /**\n * Send uniform data from this filter to its shader program on the GPU.\n *\n * Intended to be overridden by subclasses.\n *\n * @param {WebGLRenderingContext} _gl The canvas context used to compile the shader program.\n * @param {Object} _uniformLocations A map of shader uniform names to their locations.\n */\n sendUniformData(\n _gl: WebGLRenderingContext,\n _uniformLocations: TWebGLUniformLocationMap,\n ): void {\n // override by subclass\n }\n\n /**\n * If needed by a 2d filter, this functions can create an helper canvas to be used\n * remember that options.targetCanvas is available for use till end of chain.\n */\n createHelpLayer(options: T2DPipelineState) {\n if (!options.helpLayer) {\n const { sourceWidth, sourceHeight } = options;\n const helpLayer = createCanvasElementFor({\n width: sourceWidth,\n height: sourceHeight,\n });\n options.helpLayer = helpLayer;\n }\n }\n\n /**\n * Returns object representation of an instance\n * It will automatically export the default values of a filter,\n * stored in the static defaults property.\n * @return {Object} Object representation of an instance\n */\n toObject(): { type: Name } & SerializedProps {\n const defaultKeys = Object.keys(\n (this.constructor as typeof BaseFilter).defaults || {},\n ) as (keyof SerializedProps)[];\n\n return {\n type: this.type,\n ...defaultKeys.reduce<SerializedProps>((acc, key) => {\n acc[key] = this[\n key as keyof this\n ] as unknown as (typeof acc)[typeof key];\n return acc;\n }, {} as SerializedProps),\n };\n }\n\n /**\n * Returns a JSON representation of an instance\n * @return {Object} JSON\n */\n toJSON() {\n // delegate, not alias\n return this.toObject();\n }\n\n static async fromObject(\n { type, ...filterOptions }: Record<string, any>,\n _options: Abortable,\n ): Promise<BaseFilter<string, object>> {\n return new this(filterOptions);\n }\n}\n"],"names":["regex","RegExp","highPsourceCode","BaseFilter","type","this","constructor","options","_objectWithoutProperties","arguments","length","undefined","_excluded","Object","assign","defaults","getFragmentSource","identityFragmentShader","getVertexSource","vertexSource","createProgram","gl","fragmentSource","WebGLProbe","GLPrecision","getEnv","replace","vertexShader","createShader","VERTEX_SHADER","fragmentShader","FRAGMENT_SHADER","program","FabricError","shaderSource","compileShader","getShaderParameter","COMPILE_STATUS","concat","getShaderInfoLog","attachShader","linkProgram","getProgramParameter","LINK_STATUS","getProgramInfoLog","uniformLocations","getUniformLocations","uStepW","getUniformLocation","uStepH","attributeLocations","getAttributeLocations","aPosition","getAttribLocation","locations","i","sendAttributeData","aPositionData","attributeLocation","buffer","createBuffer","bindBuffer","ARRAY_BUFFER","enableVertexAttribArray","vertexAttribPointer","FLOAT","bufferData","STATIC_DRAW","_setupFrameBuffer","context","passes","width","destinationWidth","height","destinationHeight","sourceWidth","sourceHeight","deleteTexture","targetTexture","filterBackend","createTexture","framebufferTexture2D","FRAMEBUFFER","COLOR_ATTACHMENT0","TEXTURE_2D","bindFramebuffer","finish","_swapTextures","pass","temp","sourceTexture","isNeutralState","applyTo","isWebGLPipelineState","applyToWebGL","applyTo2d","_options","getCacheKey","retrieveShader","key","programCache","shader","originalTexture","bindTexture","useProgram","uniform1f","sendUniformData","viewport","drawArrays","TRIANGLE_STRIP","bindAdditionalTexture","texture","textureUnit","activeTexture","TEXTURE0","unbindAdditionalTexture","_gl","_uniformLocations","createHelpLayer","helpLayer","createCanvasElementFor","toObject","defaultKeys","keys","_objectSpread","reduce","acc","toJSON","fromObject","_ref2","_excluded2","_defineProperty"],"mappings":"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"}