Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(TS): Converting the filtering backend to ts + es6 #8403

Merged
merged 21 commits into from
Nov 19, 2022

Conversation

asturur
Copy link
Member

@asturur asturur commented Oct 30, 2022

Motivation

Continue conversion of fabricJS to TS.
Move the filtering backend and the base filter to TS.
No functionality changes, just Types + modern js.

Description

Changes

Gist

In Action

@github-actions
Copy link
Contributor

github-actions bot commented Nov 1, 2022

Build Stats

file / KB (diff) bundled minified gzipped
fabric.min.js 1076.275 (+11.662) 331.417 (+4.481) 93.398 (+1.481)

@github-actions
Copy link
Contributor

github-actions bot commented Nov 1, 2022

Coverage after merging ts-filter-backend into master will be

82.34%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
HEADER.js54%48.15%0%63.64%12, 14, 14, 14, 14, 14, 16–17, 21, 21–22, 22, 22, 24, 24, 26, 28, 30–31, 77, 77, 77
src
   cache.ts97.06%90%100%100%57
   canvas.class.ts93.36%90.22%94.12%95.54%1045, 1045–1046, 1049, 1069, 1069, 1104, 1137–1138, 1166–1167, 1200, 1208, 1318–1319, 1321–1322, 1342–1343, 1501, 1506, 1516, 1520, 472–473, 478, 487, 636–638, 683–684, 733–734, 737, 739, 782–784, 826, 831–832, 860–861
   config.ts77.27%66.67%66.67%84.62%130, 138–140, 151–153
   constants.ts100%100%100%100%
   intersection.class.ts100%100%100%100%
   pattern.class.ts92.19%85.71%100%96.30%110, 116, 127, 136, 88
   point.class.ts100%100%100%100%
   shadow.class.ts95.95%90%100%100%173, 240, 9
   static_canvas.class.ts90.21%83.99%96.77%92.82%1153–1154, 1154, 1154–1155, 1289, 1355–1356, 1359, 1408–1409, 1502, 1517, 1521, 1547–1548, 1577–1578, 1611–1612, 1653–1654, 1657, 1659, 1659, 1659, 1659, 1663, 1663, 1663–1665, 1687–1688, 1729–1730, 1733, 1735, 1735, 1735, 1735, 1739, 1739, 1739–1741, 1814, 1814–1815, 1888, 1890, 1890, 1890, 1890, 1890–1891, 1894–1895, 1895, 1895–1896, 1899, 1899, 1899, 1901, 1904, 1910, 1912–1913, 1913, 1913, 1916–1917, 1917, 1917, 1920, 279–280, 282–283, 285–286, 299–300, 302–303, 617, 643, 699–702, 902
src/brushes
   base_brush.class.ts100%100%100%100%
   circle_brush.class.ts2.99%0%0%3.92%100–101, 103, 105–107, 116, 116, 116, 118, 120, 122–124, 126–129, 137, 144, 146, 26, 31–32, 40–44, 48–52, 59–62, 70–74, 76, 84, 84, 84, 84, 84–85, 87, 87, 87–90, 92
   pattern_brush.class.ts5.26%0%0%8.33%16, 20–23, 25–26, 26, 26–29, 37–38, 40, 44, 55, 55, 55, 63–65, 65, 65, 72–73, 75–76, 76, 80
   pencil_brush.class.ts91.95%85.42%100%93.69%125–126, 155, 155–157, 279, 283, 288–289, 71–72, 87–88
   spray_brush.class.ts2.30%0%0%3.08%102–104, 106–107, 115, 115, 115, 115, 115–116, 118–119, 126–127, 129, 131–135, 144, 148–149, 149, 157, 157, 157–160, 162–165, 169–170, 172, 174–177, 180, 187–188, 190, 192–193, 195, 202–203, 205–206, 209, 209, 216, 216, 220, 25–26, 28–30, 30, 30–32, 36, 45, 52, 59, 66, 73, 80, 92–94
src/color
   color.class.ts91.67%84.51%100%94.44%325–326, 330–331, 334–335, 41, 45, 72–73, 73, 75, 75, 75–76, 78–79
   color_map.ts100%100%100%100%
   constants.ts100%100%100%100%
   index.ts100%100%100%100%
   util.ts100%100%100%100%
src/controls
   actions.ts100%100%100%100%
   changeWidth.ts100%100%100%100%
   control.class.ts93.98%88.89%90.91%97.78%236, 320, 320, 355
   controls.render.ts81.63%78%100%84.78%106, 111, 121, 121, 45, 50, 61, 61, 65–72, 81–82
   default_controls.ts72.73%50%100%100%109, 113, 120
   drag.ts100%100%100%100%
   rotate.ts20%12.50%50%22.22%44, 50, 50, 50–51, 54–56, 58, 58, 58, 58, 58–60, 60, 60–62, 64, 64, 64–66, 66, 66–67, 72, 72, 72–73, 75, 77, 79–80
   scale.ts94.41%94.74%100%93.59%129–130, 132–134, 181–183, 42
   scaleSkew.ts80.56%66.67%100%92.31%14, 28, 30, 30, 30, 32, 34
   skew.ts91.03%79.31%100%97.67%131–132, 163–164, 171, 177, 179
   util.ts100%100%100%100%
   wrapWithFireEvent.ts100%100%100%100%
   wrapWithFixedAnchor.ts100%100%100%100%
src/filters
   2d_backend.class.ts92%83.33%100%93.75%34–35
   WebGLProbe.ts51.02%50%66.67%48.28%31–33, 33, 33–34, 36–38, 46, 49–51, 51, 51–54, 56, 61, 71–72
   base_filter.class.ts22.35%20.41%38.10%20%100, 102–104, 104, 104–105, 112–114, 114, 114–115, 122–125, 125, 125–126, 132, 132, 132–135, 153, 183–188, 192–193, 193, 193–196, 196, 196, 196, 196–198, 204, 213–214, 219–223, 265–268, 284, 284, 284–285, 287, 303–305, 305, 305, 305, 305–306, 308, 310–311, 313–314, 316–318, 326–327, 329, 33, 333–335, 339, 339, 339, 343, 343, 343–344, 366, 366, 366–370, 54–55, 83–84, 86, 86, 86–87, 87, 90, 95–97, 99, 99, 99, 99, 99, 99
   blendcolor_filter.class.ts10%4.76%28.57%9.72%104, 126, 128, 128, 128–130, 135, 145–147, 155, 157–160, 162–165, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 169–172, 174–177,

@asturur asturur marked this pull request as ready for review November 1, 2022 12:39
@asturur
Copy link
Member Author

asturur commented Nov 1, 2022

i m adding base_filter class to this PR, so i don't have to wait reviews

Copy link
Contributor

@ShaMan123 ShaMan123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good
I saw what you meant about disposing and the types, I prefer your solution than any I can think of that just add complication where it isn't wanted nor needed

dispose: noop,
clearWebGLCaches: noop,
constructor() {
return this;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

??

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't know... let me remove it, i don't remember


constructor({ tileSize } = {}) {
constructor({ tileSize = config.textureSize } = {}) {
if (tileSize) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redundant check, always true, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

@@ -65,10 +68,11 @@ class WebglFilterBackend {

/**
* Pick a method to copy data from GL context to 2d canvas. In some browsers using
* drawImage should be faster, but is also bugged for a small combination of old hardware
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* drawImage should be faster, but is also bugged for a small combination of old hardware
* drawImage should be faster, but is also buggy for a small combination of old hardware

* @param {WebGLRenderingContext} sourceContext The WebGL context to copy from.
* @param {Object} pipelineState The 2D target canvas to copy on to.
*/
copyGLTo2D(gl: WebGLRenderingContext, pipelineState: TWebGLPipelineState) {
Copy link
Contributor

@ShaMan123 ShaMan123 Nov 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method can be static
I saw the code calls it with a call directive: copyGLTo2D.call(context, ...params) but there is no need since it is context less

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh I saw the assignment of copyGLTo2DPutImageData that uses context

Why are those methods standalone and copyGLTo2D is a class method?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps create a dedicated lass for these methods, passing the context to the constructor?
Instead of using call and casting types, perf-wise is identical I believe

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah this method swap here isn't a good idea, but for now i m not going to touch it

@@ -526,7 +527,7 @@ import { FabricObject } from './fabricObject.class';
this._lastScaleY = 1;
}
if (!fabric.filterBackend) {
fabric.filterBackend = fabric.initFilterBackend();
fabric.filterBackend = initFilterBackend();
Copy link
Contributor

@ShaMan123 ShaMan123 Nov 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tree shaking should relief us from this task, right?
we can declare it in the file so if it is imported it is included and that's it... as the rest of fabric
well I guess for the cdn maybe....

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm i think there are cases in which you want to swap the instance.
It was happened here, but probably a setFilterBackend method is all we need in case you want to switch from 2d to webgl on request

@asturur
Copy link
Member Author

asturur commented Nov 19, 2022

how did i add 5k of code?

@asturur
Copy link
Member Author

asturur commented Nov 19, 2022

i really don't like the 4.553 extra minified bytes whyyyy

@asturur
Copy link
Member Author

asturur commented Nov 19, 2022

Just to brag a bit, this is around 4800 bytes of code

class vs{constructor(){this.resources={}}applyFilters(t,e,i,s,r){const n=r.getContext("2d");if(!n)return;n.drawImage(e,0,0,i,s);const o={sourceWidth:i,sourceHeight:s,imageData:n.getImageData(0,0,i,s),originalEl:e,originalImageData:n.getImageData(0,0,i,s),canvasEl:r,ctx:n,filterBackend:this};t.forEach((function(t){t.applyTo(o)}));const{imageData:a}=o;return a.width===i&&a.height===s||(r.width=a.width,r.height=a.height),n.putImageData(a,0,0),o}}class _s{constructor({tileSize:t=e.textureSize}={}){this.aPosition=new Float32Array([0,0,0,1,1,0,1,1]),this.resources={},this.tileSize=t,this.setupGLContext(t,t),this.captureGPUInfo()}setupGLContext(t,e){this.dispose(),this.createWebGLCanvas(t,e),this.chooseFastestCopyGLTo2DMethod(t,e)}chooseFastestCopyGLTo2DMethod(t,i){const s=U(),r=new ArrayBuffer(t*i*4);if(e.forceGLPutImageData)return this.imageBuffer=r,void(this.copyGLTo2D=ys);const n={imageBuffer:r},o={destinationWidth:t,destinationHeight:i,targetCanvas:s};let a;s.width=t,s.height=i,a=c.window.performance.now(),this.copyGLTo2D.call(n,this.gl,o);const h=c.window.performance.now()-a;a=c.window.performance.now(),ys.call(n,this.gl,o);h>c.window.performance.now()-a&&(this.imageBuffer=r,this.copyGLTo2D=ys)}createWebGLCanvas(t,e){const i=U();i.width=t,i.height=e;const s=i.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,depth:!1,stencil:!1,antialias:!1});s&&(s.clearColor(0,0,0,0),this.canvas=i,this.gl=s)}applyFilters(t,e,i,s,r,n){const o=this.gl,a=r.getContext("2d");if(!o||!a)return;let h;n&&(h=this.getCachedTexture(n,e));const c={originalWidth:e.width||e.originalWidth||0,originalHeight:e.height||e.originalHeight||0,sourceWidth:i,sourceHeight:s,destinationWidth:i,destinationHeight:s,context:o,sourceTexture:this.createTexture(o,i,s,h?void 0:e),targetTexture:this.createTexture(o,i,s),originalTexture:h||this.createTexture(o,i,s,h?void 0:e),passes:t.length,webgl:!0,aPosition:this.aPosition,programCache:this.programCache,pass:0,filterBackend:this,targetCanvas:r},l=o.createFramebuffer();return o.bindFramebuffer(o.FRAMEBUFFER,l),t.forEach((t=>{t&&t.applyTo(c)})),function(t){const e=t.targetCanvas,i=e.width,s=e.height,r=t.destinationWidth,n=t.destinationHeight;i===r&&s===n||(e.width=r,e.height=n)}(c),this.copyGLTo2D(o,c),o.bindTexture(o.TEXTURE_2D,null),o.deleteTexture(c.sourceTexture),o.deleteTexture(c.targetTexture),o.deleteFramebuffer(l),a.setTransform(1,0,0,1,0,0),c}dispose(){this.canvas&&(this.canvas=null,this.gl=null),this.clearWebGLCaches()}clearWebGLCaches(){this.programCache={},this.textureCache={}}createTexture(t,e,i,s){const r=t.createTexture();return t.bindTexture(t.TEXTURE_2D,r),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),s?t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,s):t.texImage2D(t.TEXTURE_2D,0,t.RGBA,e,i,0,t.RGBA,t.UNSIGNED_BYTE,null),r}getCachedTexture(t,e){if(this.textureCache[t])return this.textureCache[t];{const i=this.createTexture(this.gl,e.width,e.height,e);return this.textureCache[t]=i,i}}evictCachesForKey(t){this.textureCache[t]&&(this.gl.deleteTexture(this.textureCache[t]),delete this.textureCache[t])}copyGLTo2D(t,e){const i=t.canvas,s=e.targetCanvas,r=s.getContext("2d");if(!r)return;r.translate(0,s.height),r.scale(1,-1);const n=i.height-s.height;r.drawImage(i,0,n,s.width,s.height,0,0,s.width,s.height)}captureGPUInfo(){if(this.gpuInfo)return this.gpuInfo;const t=this.gl,e={renderer:"",vendor:""};if(!t)return e;const i=t.getExtension("WEBGL_debug_renderer_info");if(i){const s=t.getParameter(i.UNMASKED_RENDERER_WEBGL),r=t.getParameter(i.UNMASKED_VENDOR_WEBGL);s&&(e.renderer=s.toLowerCase()),r&&(e.vendor=r.toLowerCase())}return this.gpuInfo=e,e}}function ys(t,e){const i=e.targetCanvas.getContext("2d"),s=e.destinationWidth,r=e.destinationHeight,n=s*r*4;if(!i)return;const o=new Uint8Array(this.imageBuffer,0,n),a=new Uint8ClampedArray(this.imageBuffer,0,n);t.readPixels(0,0,s,r,t.RGBA,t.UNSIGNED_BYTE,o);const h=new ImageData(a,s,r);i.putImageData(h,0,0)}var xs;!function(t){t.low="lowp",t.medium="mediump",t.high="highp"}(xs||(xs={}));const bs=new class{testPrecision(t,e){const i=`precision ${e} float;\nvoid main(){}`,s=t.createShader(t.FRAGMENT_SHADER);return!!s&&(t.shaderSource(s,i),t.compileShader(s),!!t.getShaderParameter(s,t.COMPILE_STATUS))}queryWebGL(){if(c.isLikelyNode)return;const t=U().getContext("webgl");t&&(this.maxTextureSize=t.getParameter(t.MAX_TEXTURE_SIZE),this.webGLPrecision=Object.values(xs).find((e=>this.testPrecision(t,e))),console.log(`fabric: max texture size ${this.maxTextureSize}`))}isSupported(t){return this.maxTextureSize&&this.maxTextureSize>=t}};function Cs(){return bs.queryWebGL(),e.enableGLFiltering&&bs.isSupported(e.textureSize)?new _s({tileSize:e.textureSize}):new vs}c.Canvas2dFilterBackend=vs,c.WebglFilterBackend=_s,c.initFilterBackend=Cs

And is the totality of Canvas2dFilterBackend, WebglFilterBackend initFilterBackend and webglprobe.
The basicFilter is another 4600 bytes

class ws{constructor(t={}){this.type="BaseFilter",this.setOptions(t)}initialize(t={}){this.setOptions(t)}setOptions(t){Object.assign(this,t)}createProgram(t,e=this.fragmentSource,i=this.vertexSource){bs.webGLPrecision&&bs.webGLPrecision!==xs.high&&(e=e.replace(new RegExp(Ss,"g"),Ss.replace(xs.high,bs.webGLPrecision)));const s=t.createShader(t.VERTEX_SHADER),r=t.createShader(t.FRAGMENT_SHADER),n=t.createProgram();if(!s||!r||!n)throw new Error("Vertex, fragment shader or program creation error");if(t.shaderSource(s,i),t.compileShader(s),!t.getShaderParameter(s,t.COMPILE_STATUS))throw new Error(`Vertex shader compile error for ${this.type}: ${t.getShaderInfoLog(s)}`);if(t.shaderSource(r,e),t.compileShader(r),!t.getShaderParameter(r,t.COMPILE_STATUS))throw new Error(`Fragment shader compile error for ${this.type}: ${t.getShaderInfoLog(r)}`);if(t.attachShader(n,s),t.attachShader(n,r),t.linkProgram(n),!t.getProgramParameter(n,t.LINK_STATUS))throw new Error('Shader link error for "${this.type}" '+t.getProgramInfoLog(n));const o=this.getUniformLocations(t,n)||{};return o.uStepW=t.getUniformLocation(n,"uStepW"),o.uStepH=t.getUniformLocation(n,"uStepH"),{program:n,attributeLocations:this.getAttributeLocations(t,n),uniformLocations:o}}getAttributeLocations(t,e){return{aPosition:t.getAttribLocation(e,"aPosition")}}sendAttributeData(t,e,i){const s=e.aPosition,r=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,r),t.enableVertexAttribArray(s),t.vertexAttribPointer(s,2,t.FLOAT,!1,0,0),t.bufferData(t.ARRAY_BUFFER,i,t.STATIC_DRAW)}_setupFrameBuffer(t){const e=t.context;if(t.passes>1){const i=t.destinationWidth,s=t.destinationHeight;t.sourceWidth===i&&t.sourceHeight===s||(e.deleteTexture(t.targetTexture),t.targetTexture=t.filterBackend.createTexture(e,i,s)),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,t.targetTexture,0)}else e.bindFramebuffer(e.FRAMEBUFFER,null),e.finish()}_swapTextures(t){t.passes--,t.pass++;const e=t.targetTexture;t.targetTexture=t.sourceTexture,t.sourceTexture=e}isNeutralState(){const t=this.mainParameter,e=this.__proto__;return!!t&&(Array.isArray(e[t])&&Array.isArray(this[t])?e[t].every(((e,i)=>e===this[t][i])):e[t]===this[t])}applyTo(t){(t=>void 0!==t.webgl)(t)?(this._setupFrameBuffer(t),this.applyToWebGL(t),this._swapTextures(t)):this.applyTo2d(t)}retrieveShader(t){return t.programCache[this.type]||(t.programCache[this.type]=this.createProgram(t.context)),t.programCache[this.type]}applyToWebGL(t){const e=t.context,i=this.retrieveShader(t);0===t.pass&&t.originalTexture?e.bindTexture(e.TEXTURE_2D,t.originalTexture):e.bindTexture(e.TEXTURE_2D,t.sourceTexture),e.useProgram(i.program),this.sendAttributeData(e,i.attributeLocations,t.aPosition),e.uniform1f(i.uniformLocations.uStepW,1/t.sourceWidth),e.uniform1f(i.uniformLocations.uStepH,1/t.sourceHeight),this.sendUniformData(e,i.uniformLocations),e.viewport(0,0,t.destinationWidth,t.destinationHeight),e.drawArrays(e.TRIANGLE_STRIP,0,4)}bindAdditionalTexture(t,e,i){t.activeTexture(i),t.bindTexture(t.TEXTURE_2D,e),t.activeTexture(t.TEXTURE0)}unbindAdditionalTexture(t,e){t.activeTexture(e),t.bindTexture(t.TEXTURE_2D,null),t.activeTexture(t.TEXTURE0)}getMainParameter(){return this.mainParameter?this[this.mainParameter]:void 0}setMainParameter(t){this.mainParameter&&(this[this.mainParameter]=t)}createHelpLayer(t){if(!t.helpLayer){const e=U();e.width=t.sourceWidth,e.height=t.sourceHeight,t.helpLayer=e}}toObject(){const t=this.mainParameter;return Object.assign({type:this.type},t?{[t]:this[t]}:{})}toJSON(){return this.toObject()}}ws.fromObject=function(t){return Promise.resolve(new c.Image.filters[t.type](t))},Object.assign(ws.prototype,{vertexSource:"\n    attribute vec2 aPosition;\n    varying vec2 vTexCoord;\n    void main() {\n      vTexCoord = aPosition;\n      gl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n    }",fragmentSource:`\n    ${Ss};\n    varying vec2 vTexCoord;\n    uniform sampler2D uTexture;\n    void main() {\n      gl_FragColor = texture2D(uTexture, vTexCoord);\n    }`}),c.Image.filters={BaseFilter:ws}

And this is all the code we touched in this PR, so what, it doubled in size?

@asturur
Copy link
Member Author

asturur commented Nov 19, 2022

base filter before PR 4161 bytes ( 450 less )

Image.filters.BaseFilter=e.util.createClass({type:"BaseFilter",vertexSource:"attribute vec2 aPosition;\nvarying vec2 vTexCoord;\nvoid main() {\nvTexCoord = aPosition;\ngl_Position = vec4(aPosition * 2.0 - 1.0, 0.0, 1.0);\n}",fragmentSource:"precision highp float;\nvarying vec2 vTexCoord;\nuniform sampler2D uTexture;\nvoid main() {\ngl_FragColor = texture2D(uTexture, vTexCoord);\n}",initialize:function(t){t&&this.setOptions(t)},setOptions:function(t){for(var e in t)this[e]=t[e]},createProgram:function(t,e,i){e=e||this.fragmentSource,i=i||this.vertexSource,"highp"!==_s.webGLPrecision&&(e=e.replace(new RegExp("precision highp float","g"),`precision ${_s.webGLPrecision} float`));var s=t.createShader(t.VERTEX_SHADER);if(t.shaderSource(s,i),t.compileShader(s),!t.getShaderParameter(s,t.COMPILE_STATUS))throw new Error("Vertex shader compile error for "+this.type+": "+t.getShaderInfoLog(s));var r=t.createShader(t.FRAGMENT_SHADER);if(t.shaderSource(r,e),t.compileShader(r),!t.getShaderParameter(r,t.COMPILE_STATUS))throw new Error("Fragment shader compile error for "+this.type+": "+t.getShaderInfoLog(r));var n=t.createProgram();if(t.attachShader(n,s),t.attachShader(n,r),t.linkProgram(n),!t.getProgramParameter(n,t.LINK_STATUS))throw new Error('Shader link error for "${this.type}" '+t.getProgramInfoLog(n));var o=this.getAttributeLocations(t,n),a=this.getUniformLocations(t,n)||{};return a.uStepW=t.getUniformLocation(n,"uStepW"),a.uStepH=t.getUniformLocation(n,"uStepH"),{program:n,attributeLocations:o,uniformLocations:a}},getAttributeLocations:function(t,e){return{aPosition:t.getAttribLocation(e,"aPosition")}},getUniformLocations:function(){return{}},sendAttributeData:function(t,e,i){var s=e.aPosition,r=t.createBuffer();t.bindBuffer(t.ARRAY_BUFFER,r),t.enableVertexAttribArray(s),t.vertexAttribPointer(s,2,t.FLOAT,!1,0,0),t.bufferData(t.ARRAY_BUFFER,i,t.STATIC_DRAW)},_setupFrameBuffer:function(t){var e,i,s=t.context;t.passes>1?(e=t.destinationWidth,i=t.destinationHeight,t.sourceWidth===e&&t.sourceHeight===i||(s.deleteTexture(t.targetTexture),t.targetTexture=t.filterBackend.createTexture(s,e,i)),s.framebufferTexture2D(s.FRAMEBUFFER,s.COLOR_ATTACHMENT0,s.TEXTURE_2D,t.targetTexture,0)):(s.bindFramebuffer(s.FRAMEBUFFER,null),s.finish())},_swapTextures:function(t){t.passes--,t.pass++;var e=t.targetTexture;t.targetTexture=t.sourceTexture,t.sourceTexture=e},isNeutralState:function(){var t=this.mainParameter,i=e.Image.filters[this.type].prototype;if(t){if(Array.isArray(i[t])){for(var s=i[t].length;s--;)if(this[t][s]!==i[t][s])return!1;return!0}return i[t]===this[t]}return!1},applyTo:function(t){t.webgl?(this._setupFrameBuffer(t),this.applyToWebGL(t),this._swapTextures(t)):this.applyTo2d(t)},retrieveShader:function(t){return t.programCache.hasOwnProperty(this.type)||(t.programCache[this.type]=this.createProgram(t.context)),t.programCache[this.type]},applyToWebGL:function(t){var e=t.context,i=this.retrieveShader(t);0===t.pass&&t.originalTexture?e.bindTexture(e.TEXTURE_2D,t.originalTexture):e.bindTexture(e.TEXTURE_2D,t.sourceTexture),e.useProgram(i.program),this.sendAttributeData(e,i.attributeLocations,t.aPosition),e.uniform1f(i.uniformLocations.uStepW,1/t.sourceWidth),e.uniform1f(i.uniformLocations.uStepH,1/t.sourceHeight),this.sendUniformData(e,i.uniformLocations),e.viewport(0,0,t.destinationWidth,t.destinationHeight),e.drawArrays(e.TRIANGLE_STRIP,0,4)},bindAdditionalTexture:function(t,e,i){t.activeTexture(i),t.bindTexture(t.TEXTURE_2D,e),t.activeTexture(t.TEXTURE0)},unbindAdditionalTexture:function(t,e){t.activeTexture(e),t.bindTexture(t.TEXTURE_2D,null),t.activeTexture(t.TEXTURE0)},getMainParameter:function(){return this[this.mainParameter]},setMainParameter:function(t){this[this.mainParameter]=t},sendUniformData:function(){},createHelpLayer:function(t){if(!t.helpLayer){var e=document.createElement("canvas");e.width=t.sourceWidth,e.height=t.sourceHeight,t.helpLayer=e}},toObject:function(){var t={type:this.type},e=this.mainParameter;return e&&(t[e]=this[e]),t},toJSON:function(){return this.toObject()}}),e.Image.filters.BaseFilter.fromObject=function(t){return Promise.resolve(new e.Image.filters[t.type](t))}}()

The rest was 5860

const vs=["lowp","mediump","highp"];const _s=new class{constructor(){this.initialized=!1}get maxTextureSize(){return this.queryWebGL(),this._maxTextureSize}get webGLPrecision(){return this.queryWebGL(),this._webGLPrecision}testPrecision(t,e){const i=`precision ${e} float;\nvoid main(){}`,s=t.createShader(t.FRAGMENT_SHADER);return t.shaderSource(s,i),t.compileShader(s),!!t.getShaderParameter(s,t.COMPILE_STATUS)}queryWebGL(){if(this.initialized||c.isLikelyNode)return;const t=U(),e=t.getContext("webgl")||t.getContext("experimental-webgl");e&&(this._maxTextureSize=e.getParameter(e.MAX_TEXTURE_SIZE),this._webGLPrecision=vs.find((t=>this.testPrecision(e,t))),console.log(`fabric: max texture size ${this._maxTextureSize}`)),this.initialized=!0}isSupported(t){return this.maxTextureSize&&this.maxTextureSize>=t}};function ys(t,e){var i=t.canvas,s=e.targetCanvas,r=s.getContext("2d");r.translate(0,s.height),r.scale(1,-1);var n=i.height-s.height;r.drawImage(i,0,n,s.width,s.height,0,0,s.width,s.height)}function xs(t,e){var i=e.targetCanvas.getContext("2d"),s=e.destinationWidth,r=e.destinationHeight,n=s*r*4,o=new Uint8Array(this.imageBuffer,0,n),a=new Uint8ClampedArray(this.imageBuffer,0,n);t.readPixels(0,0,s,r,t.RGBA,t.UNSIGNED_BYTE,o);var h=new ImageData(a,s,r);i.putImageData(h,0,0)}!function(t){var i=(typeof exports!=="undefined"?exports:window).fabric;function s(t){t&&t.tileSize&&(this.tileSize=t.tileSize),this.setupGLContext(this.tileSize,this.tileSize),this.captureGPUInfo()}i.initFilterBackend=function(){return e.enableGLFiltering&&_s.isSupported(e.textureSize)?new i.WebglFilterBackend({tileSize:e.textureSize}):i.Canvas2dFilterBackend?new i.Canvas2dFilterBackend:void 0},i.WebglFilterBackend=s,s.prototype={tileSize:e.textureSize,resources:{},setupGLContext:function(t,e){this.dispose(),this.createWebGLCanvas(t,e),this.aPosition=new Float32Array([0,0,0,1,1,0,1,1]),this.chooseFastestCopyGLTo2DMethod(t,e)},chooseFastestCopyGLTo2DMethod:function(t,s){var r,n=void 0!==window.performance;try{new ImageData(1,1),r=!0}catch(t){r=!1}var o="undefined"!=typeof ArrayBuffer,a="undefined"!=typeof Uint8ClampedArray;if(n&&r&&o&&a){var h=i.util.createCanvasElement(),c=new ArrayBuffer(t*s*4);if(e.forceGLPutImageData)return this.imageBuffer=c,void(this.copyGLTo2D=xs);var l,u,d={imageBuffer:c,destinationWidth:t,destinationHeight:s,targetCanvas:h};h.width=t,h.height=s,l=window.performance.now(),ys.call(d,this.gl,d),u=window.performance.now()-l,l=window.performance.now(),xs.call(d,this.gl,d),u>window.performance.now()-l?(this.imageBuffer=c,this.copyGLTo2D=xs):this.copyGLTo2D=ys}},createWebGLCanvas:function(t,e){var s=i.util.createCanvasElement();s.width=t,s.height=e;var r={alpha:!0,premultipliedAlpha:!1,depth:!1,stencil:!1,antialias:!1},n=s.getContext("webgl",r);n||(n=s.getContext("experimental-webgl",r)),n&&(n.clearColor(0,0,0,0),this.canvas=s,this.gl=n)},applyFilters:function(t,e,i,s,r,n){var o,a=this.gl;n&&(o=this.getCachedTexture(n,e));var h={originalWidth:e.width||e.originalWidth,originalHeight:e.height||e.originalHeight,sourceWidth:i,sourceHeight:s,destinationWidth:i,destinationHeight:s,context:a,sourceTexture:this.createTexture(a,i,s,!o&&e),targetTexture:this.createTexture(a,i,s),originalTexture:o||this.createTexture(a,i,s,!o&&e),passes:t.length,webgl:!0,aPosition:this.aPosition,programCache:this.programCache,pass:0,filterBackend:this,targetCanvas:r},c=a.createFramebuffer();return a.bindFramebuffer(a.FRAMEBUFFER,c),t.forEach((function(t){t&&t.applyTo(h)})),function(t){var e=t.targetCanvas,i=e.width,s=e.height,r=t.destinationWidth,n=t.destinationHeight;i===r&&s===n||(e.width=r,e.height=n)}(h),this.copyGLTo2D(a,h),a.bindTexture(a.TEXTURE_2D,null),a.deleteTexture(h.sourceTexture),a.deleteTexture(h.targetTexture),a.deleteFramebuffer(c),r.getContext("2d").setTransform(1,0,0,1,0,0),h},dispose:function(){this.canvas&&(this.canvas=null,this.gl=null),this.clearWebGLCaches()},clearWebGLCaches:function(){this.programCache={},this.textureCache={}},createTexture:function(t,e,i,s){var r=t.createTexture();return t.bindTexture(t.TEXTURE_2D,r),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),s?t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,s):t.texImage2D(t.TEXTURE_2D,0,t.RGBA,e,i,0,t.RGBA,t.UNSIGNED_BYTE,null),r},getCachedTexture:function(t,e){if(this.textureCache[t])return this.textureCache[t];var i=this.createTexture(this.gl,e.width,e.height,e);return this.textureCache[t]=i,i},evictCachesForKey:function(t){this.textureCache[t]&&(this.gl.deleteTexture(this.textureCache[t]),delete this.textureCache[t])},copyGLTo2D:ys,captureGPUInfo:function(){if(this.gpuInfo)return this.gpuInfo;var t=this.gl,e={renderer:"",vendor:""};if(!t)return e;var i=t.getExtension("WEBGL_debug_renderer_info");if(i){var s=t.getParameter(i.UNMASKED_RENDERER_WEBGL),r=t.getParameter(i.UNMASKED_VENDOR_WEBGL);s&&(e.renderer=s.toLowerCase()),r&&(e.vendor=r.toLowerCase())}return this.gpuInfo=e,e}}}(),function(t){var e=function(){};function i(){}(typeof exports!=="undefined"?exports:window).fabric.Canvas2dFilterBackend=i,i.prototype={evictCachesForKey:e,dispose:e,clearWebGLCaches:e,resources:{},applyFilters:function(t,e,i,s,r){var n=r.getContext("2d");n.drawImage(e,0,0,i,s);var o={sourceWidth:i,sourceHeight:s,imageData:n.getImageData(0,0,i,s),originalEl:e,originalImageData:n.getImageData(0,0,i,s),canvasEl:r,ctx:n,filterBackend:this};return t.forEach((function(t){t.applyTo(o)})),o.imageData.width===i&&o.imageData.height===s||(r.width=o.imageData.width,r.height=o.imageData.height),n.putImageData(o.imageData,0,0),o}}}(),function(t){var e=(typeof exports!=="undefined"?exports:window)

@asturur
Copy link
Member Author

asturur commented Nov 19, 2022

ok i got really crazy on this... if you just make a ls -l you will notice that:
master:

-rw-r--r--  1 abogazzi  staff   324118 Nov 19 15:37 fabric.min.js

while this PR

-rw-r--r--  1 abogazzi  staff   323139 Nov 19 15:46 fabric.min.js

So is 1k smaller and not 4.5k bigger.

@asturur asturur merged commit 46f4759 into master Nov 19, 2022
@ShaMan123
Copy link
Contributor

ShaMan123 commented Nov 19, 2022

In some ci PR I fixed the false reporting. It was caused due to changes in the index file that were accounted for in the master stats wrongly

frankrousseau pushed a commit to cgwire/fabric.js that referenced this pull request Jan 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants