@johnfmorton/some-shade 0.1.0-beta.7 → 0.1.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.0-beta.8
4
+
5
+ - Fix mobile crashes when using multiple instances on one page
6
+ - Render-then-snapshot architecture: WebGL context is created, used, and torn down per render instead of held persistently
7
+ - Cap devicePixelRatio at 2 to reduce canvas memory on 3×+ mobile screens
8
+ - Global render queue serialises WebGL across all instances (at most one context at a time)
9
+ - IntersectionObserver defers rendering for off-screen instances until they scroll into view
10
+
11
+ ## 0.1.0-beta.7
12
+
13
+ - Guard custom element registration against double-define
14
+
3
15
  ## 0.1.0-beta.6
4
16
 
5
17
  - Publish as `latest` dist-tag to fix missing sidebar links (Repository, Homepage, Issues) on npmjs.com
package/dist/index.d.ts CHANGED
@@ -35,27 +35,21 @@ export declare class SomeShadeImage extends LitElement {
35
35
  dotOffsetY: number;
36
36
  bgColor: string;
37
37
  private _webglAvailable;
38
- private _canvas;
39
- private _gl;
40
- private _programInfo;
41
- private _textureInfo;
42
- private _quadBuffer;
43
- private _currentEffect;
38
+ private _snapshotUrl;
44
39
  private _image;
45
- private _resizeObserver;
40
+ private _observer;
41
+ private _visible;
42
+ private _needsRender;
46
43
  render(): TemplateResult<1>;
47
- firstUpdated(): void;
44
+ connectedCallback(): void;
48
45
  updated(changed: PropertyValues): void;
49
46
  disconnectedCallback(): void;
50
47
  private _loadImage;
51
- private _uploadTexture;
52
- private _sizeCanvas;
53
- private _handleResize;
54
- private _setupProgram;
48
+ private _scheduleRender;
49
+ private _renderEffect;
50
+ private _revokeSnapshot;
55
51
  private _getUniformValues;
56
52
  private _parseHexColor;
57
- private _renderFrame;
58
- private _cleanup;
59
53
  }
60
54
 
61
55
  export declare interface UniformDefinition {
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("lit"),s=require("lit/decorators.js");function C(t){return t.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function b(t,e,o){const a=t.createShader(e);if(!a)throw new Error("Failed to create shader");if(t.shaderSource(a,o),t.compileShader(a),!t.getShaderParameter(a,t.COMPILE_STATUS)){const n=t.getShaderInfoLog(a);throw t.deleteShader(a),new Error(`Shader compile error: ${n}`)}return a}function R(t,e,o){const a=b(t,t.VERTEX_SHADER,e),n=b(t,t.FRAGMENT_SHADER,o),r=t.createProgram();if(!r)throw new Error("Failed to create program");if(t.attachShader(r,a),t.attachShader(r,n),t.linkProgram(r),!t.getProgramParameter(r,t.LINK_STATUS)){const l=t.getProgramInfoLog(r);throw t.deleteProgram(r),new Error(`Program link error: ${l}`)}t.deleteShader(a),t.deleteShader(n);const f=new Map,x=t.getProgramParameter(r,t.ACTIVE_ATTRIBUTES);for(let l=0;l<x;l++){const d=t.getActiveAttrib(r,l);d&&f.set(d.name,t.getAttribLocation(r,d.name))}const g=new Map,E=t.getProgramParameter(r,t.ACTIVE_UNIFORMS);for(let l=0;l<E;l++){const d=t.getActiveUniform(r,l);if(d){const v=t.getUniformLocation(r,d.name);v&&g.set(d.name,v)}}return{program:r,attribLocations:f,uniformLocations:g}}function S(t,e,o){for(const[a,n]of Object.entries(o)){const r=e.uniformLocations.get(a);if(r){if(typeof n=="number")t.uniform1f(r,n);else if(Array.isArray(n))switch(n.length){case 2:t.uniform2fv(r,n);break;case 3:t.uniform3fv(r,n);break;case 4:t.uniform4fv(r,n);break}}}}function T(t,e){const o=t.createTexture();if(!o)throw new Error("Failed to create texture");return t.bindTexture(t.TEXTURE_2D,o),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),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),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),{texture:o,width:e.naturalWidth,height:e.naturalHeight}}function A(t,e){const o=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),a=t.createBuffer();if(!a)throw new Error("Failed to create buffer");t.bindBuffer(t.ARRAY_BUFFER,a),t.bufferData(t.ARRAY_BUFFER,o,t.STATIC_DRAW);const n=4*Float32Array.BYTES_PER_ELEMENT,r=e.attribLocations.get("a_position");r!==void 0&&r!==-1&&(t.enableVertexAttribArray(r),t.vertexAttribPointer(r,2,t.FLOAT,!1,n,0));const f=e.attribLocations.get("a_texCoord");return f!==void 0&&f!==-1&&(t.enableVertexAttribArray(f),t.vertexAttribPointer(f,2,t.FLOAT,!1,n,2*Float32Array.BYTES_PER_ELEMENT)),a}function w(t){t.drawArrays(t.TRIANGLE_STRIP,0,4)}const I=`precision mediump float;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const v=require("lit"),u=require("lit/decorators.js");function k(e){return e.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function S(e,r,a){const t=e.createShader(r);if(!t)throw new Error("Failed to create shader");if(e.shaderSource(t,a),e.compileShader(t),!e.getShaderParameter(t,e.COMPILE_STATUS)){const i=e.getShaderInfoLog(t);throw e.deleteShader(t),new Error(`Shader compile error: ${i}`)}return t}function w(e,r,a){const t=S(e,e.VERTEX_SHADER,r),i=S(e,e.FRAGMENT_SHADER,a),n=e.createProgram();if(!n)throw new Error("Failed to create program");if(e.attachShader(n,t),e.attachShader(n,i),e.linkProgram(n),!e.getProgramParameter(n,e.LINK_STATUS)){const f=e.getProgramInfoLog(n);throw e.deleteProgram(n),new Error(`Program link error: ${f}`)}e.deleteShader(t),e.deleteShader(i);const o=new Map,_=e.getProgramParameter(n,e.ACTIVE_ATTRIBUTES);for(let f=0;f<_;f++){const c=e.getActiveAttrib(n,f);c&&o.set(c.name,e.getAttribLocation(n,c.name))}const d=new Map,m=e.getProgramParameter(n,e.ACTIVE_UNIFORMS);for(let f=0;f<m;f++){const c=e.getActiveUniform(n,f);if(c){const h=e.getUniformLocation(n,c.name);h&&d.set(c.name,h)}}return{program:n,attribLocations:o,uniformLocations:d}}function D(e,r,a){for(const[t,i]of Object.entries(a)){const n=r.uniformLocations.get(t);if(n){if(typeof i=="number")e.uniform1f(n,i);else if(Array.isArray(i))switch(i.length){case 2:e.uniform2fv(n,i);break;case 3:e.uniform3fv(n,i);break;case 4:e.uniform4fv(n,i);break}}}}function L(e,r){const a=e.createTexture();if(!a)throw new Error("Failed to create texture");return e.bindTexture(e.TEXTURE_2D,a),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,r),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),{texture:a,width:r.naturalWidth,height:r.naturalHeight}}function P(e,r){const a=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),t=e.createBuffer();if(!t)throw new Error("Failed to create buffer");e.bindBuffer(e.ARRAY_BUFFER,t),e.bufferData(e.ARRAY_BUFFER,a,e.STATIC_DRAW);const i=4*Float32Array.BYTES_PER_ELEMENT,n=r.attribLocations.get("a_position");n!==void 0&&n!==-1&&(e.enableVertexAttribArray(n),e.vertexAttribPointer(n,2,e.FLOAT,!1,i,0));const o=r.attribLocations.get("a_texCoord");return o!==void 0&&o!==-1&&(e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,i,2*Float32Array.BYTES_PER_ELEMENT)),t}function V(e){e.drawArrays(e.TRIANGLE_STRIP,0,4)}const O=`precision mediump float;
2
2
 
3
3
  varying vec2 v_texCoord;
4
4
 
@@ -54,7 +54,7 @@ void main() {
54
54
 
55
55
  gl_FragColor = vec4(outR, outG, outB, color.a);
56
56
  }
57
- `,h=`attribute vec2 a_position;
57
+ `,y=`attribute vec2 a_position;
58
58
  attribute vec2 a_texCoord;
59
59
  varying vec2 v_texCoord;
60
60
 
@@ -62,7 +62,7 @@ void main() {
62
62
  gl_Position = vec4(a_position, 0.0, 1.0);
63
63
  v_texCoord = a_texCoord;
64
64
  }
65
- `,U={name:"halftone-cmyk",fragmentShader:I,vertexShader:h,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"}]},k=`precision mediump float;
65
+ `,F={name:"halftone-cmyk",fragmentShader:O,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"}]},z=`precision mediump float;
66
66
 
67
67
  varying vec2 v_texCoord;
68
68
 
@@ -97,7 +97,7 @@ void main() {
97
97
 
98
98
  gl_FragColor = vec4(result, color.a);
99
99
  }
100
- `,P={name:"halftone-duotone",fragmentShader:k,vertexShader:h,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},D=`precision mediump float;
100
+ `,M={name:"halftone-duotone",fragmentShader:z,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},I=`precision mediump float;
101
101
 
102
102
  varying vec2 v_texCoord;
103
103
 
@@ -166,7 +166,7 @@ void main() {
166
166
  vec2 sortedUV = spanStartUV + step * float(rank);
167
167
  gl_FragColor = texture2D(u_image, sortedUV);
168
168
  }
169
- `,L={name:"pixel-sort",fragmentShader:D,vertexShader:h,uniforms:[{name:"u_threshold",type:"float",default:.5,attribute:"threshold"},{name:"u_direction",type:"float",default:0,attribute:"sort-direction"},{name:"u_span",type:"float",default:64,attribute:"sort-span"}]},z=`precision mediump float;
169
+ `,N={name:"pixel-sort",fragmentShader:I,vertexShader:y,uniforms:[{name:"u_threshold",type:"float",default:.5,attribute:"threshold"},{name:"u_direction",type:"float",default:0,attribute:"sort-direction"},{name:"u_span",type:"float",default:64,attribute:"sort-span"}]},B=`precision mediump float;
170
170
 
171
171
  varying vec2 v_texCoord;
172
172
 
@@ -211,15 +211,15 @@ void main() {
211
211
 
212
212
  gl_FragColor = vec4(result, 1.0);
213
213
  }
214
- `,F={name:"dot-grid",fragmentShader:z,vertexShader:h,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"}]},m=new Map;function c(t){m.set(t.name,t)}function y(t){return m.get(t)}function V(){return Array.from(m.keys())}c(U);c(P);c(L);c(F);var O=Object.defineProperty,u=(t,e,o,a)=>{for(var n=void 0,r=t.length-1,f;r>=0;r--)(f=t[r])&&(n=f(e,o,n)||n);return n&&O(e,o,n),n};const p=class p extends _.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.duotoneColor="#0099cc",this.angle=0,this.threshold=.5,this.sortDirection=0,this.sortSpan=64,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this._webglAvailable=!0,this._canvas=null,this._gl=null,this._programInfo=null,this._textureInfo=null,this._quadBuffer=null,this._currentEffect=null,this._image=null,this._resizeObserver=null}render(){return this._webglAvailable?_.html`<canvas></canvas>`:_.html`<img .src=${this.src} alt="" />`}firstUpdated(){if(this._webglAvailable&&(this._canvas=this.shadowRoot.querySelector("canvas"),!!this._canvas)){if(this._gl=C(this._canvas),!this._gl){this._webglAvailable=!1,this.classList.add("webgl-unavailable");return}this._resizeObserver=new ResizeObserver(()=>this._handleResize()),this._resizeObserver.observe(this),this.src&&this._loadImage(this.src)}}updated(e){if(this._gl){if(e.has("src")&&this.src){this._loadImage(this.src);return}if(e.has("effect")){this._setupProgram(),this._renderFrame();return}this._renderFrame()}}disconnectedCallback(){var e;super.disconnectedCallback(),(e=this._resizeObserver)==null||e.disconnect(),this._cleanup()}_loadImage(e){const o=new Image;o.crossOrigin="anonymous",o.onload=()=>{this._image=o,this._uploadTexture(),this._sizeCanvas(),this._setupProgram(),this._renderFrame()},o.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${e}`)},o.src=e}_uploadTexture(){!this._gl||!this._image||(this._textureInfo&&this._gl.deleteTexture(this._textureInfo.texture),this._textureInfo=T(this._gl,this._image))}_sizeCanvas(){if(!this._canvas||!this._textureInfo)return;const e=window.devicePixelRatio||1,o=this._textureInfo.width,a=this._textureInfo.height;this._canvas.width=o*e,this._canvas.height=a*e,this._canvas.style.aspectRatio=`${o} / ${a}`}_handleResize(){this._renderFrame()}_setupProgram(){if(!this._gl)return;const e=y(this.effect);if(!e){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}this._programInfo&&this._gl.deleteProgram(this._programInfo.program),this._currentEffect=e,this._programInfo=R(this._gl,e.vertexShader,e.fragmentShader),this._quadBuffer&&this._gl.deleteBuffer(this._quadBuffer),this._gl.useProgram(this._programInfo.program),this._quadBuffer=A(this._gl,this._programInfo)}_getUniformValues(){const e={};return this._textureInfo&&(e.u_resolution=[this._textureInfo.width*(window.devicePixelRatio||1),this._textureInfo.height*(window.devicePixelRatio||1)],e.u_dotRadius=this.dotRadius,e.u_gridSize=this.gridSize,this.effect==="halftone-cmyk"?(e.u_angleC=this.angleC,e.u_angleM=this.angleM,e.u_angleY=this.angleY,e.u_angleK=this.angleK):this.effect==="halftone-duotone"?(e.u_duotoneColor=this._parseHexColor(this.duotoneColor),e.u_angle=this.angle):this.effect==="pixel-sort"?(e.u_threshold=this.threshold,e.u_direction=this.sortDirection,e.u_span=this.sortSpan):this.effect==="dot-grid"&&(e.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],e.u_bgColor=this._parseHexColor(this.bgColor))),e}_parseHexColor(e){const o=e.replace("#",""),a=parseInt(o.substring(0,2),16)/255,n=parseInt(o.substring(2,4),16)/255,r=parseInt(o.substring(4,6),16)/255;return[a,n,r]}_renderFrame(){const e=this._gl;if(!e||!this._programInfo||!this._textureInfo||!this._canvas)return;e.viewport(0,0,this._canvas.width,this._canvas.height),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT),e.useProgram(this._programInfo.program),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this._textureInfo.texture);const o=this._programInfo.uniformLocations.get("u_image");o&&e.uniform1i(o,0),S(e,this._programInfo,this._getUniformValues()),e.bindBuffer(e.ARRAY_BUFFER,this._quadBuffer);const a=4*Float32Array.BYTES_PER_ELEMENT,n=this._programInfo.attribLocations.get("a_position");n!==void 0&&n!==-1&&(e.enableVertexAttribArray(n),e.vertexAttribPointer(n,2,e.FLOAT,!1,a,0));const r=this._programInfo.attribLocations.get("a_texCoord");r!==void 0&&r!==-1&&(e.enableVertexAttribArray(r),e.vertexAttribPointer(r,2,e.FLOAT,!1,a,2*Float32Array.BYTES_PER_ELEMENT)),w(e)}_cleanup(){this._gl&&(this._textureInfo&&this._gl.deleteTexture(this._textureInfo.texture),this._programInfo&&this._gl.deleteProgram(this._programInfo.program),this._quadBuffer&&this._gl.deleteBuffer(this._quadBuffer),this._gl=null,this._programInfo=null,this._textureInfo=null,this._quadBuffer=null)}};p.styles=_.css`
214
+ `,Y={name:"dot-grid",fragmentShader:B,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"}]},E=new Map;function p(e){E.set(e.name,e)}function U(e){return E.get(e)}function K(){return Array.from(E.keys())}p(F);p(M);p(N);p(Y);var X=Object.defineProperty,l=(e,r,a,t)=>{for(var i=void 0,n=e.length-1,o;n>=0;n--)(o=e[n])&&(i=o(r,a,i)||i);return i&&X(r,a,i),i};const G=2;let C=Promise.resolve();function T(e){const r=C.then(e,e);return C=r,r}const W=new Set(["effect","dotRadius","gridSize","angleC","angleM","angleY","angleK","duotoneColor","angle","threshold","sortDirection","sortSpan","dotOffsetX","dotOffsetY","bgColor"]),R=class R extends v.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.duotoneColor="#0099cc",this.angle=0,this.threshold=.5,this.sortDirection=0,this.sortSpan=64,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this._webglAvailable=!0,this._snapshotUrl="",this._image=null,this._observer=null,this._visible=!1,this._needsRender=!1}render(){return this._webglAvailable?v.html`<img src=${this._snapshotUrl||this.src} alt="" />`:v.html`<img src=${this.src} alt="" />`}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(r=>{var t;const a=this._visible;this._visible=((t=r[0])==null?void 0:t.isIntersecting)??!1,this._visible&&!a&&this._needsRender&&(this._needsRender=!1,T(()=>this._renderEffect()))},{rootMargin:"200px"}),this._observer.observe(this)}updated(r){if(r.has("src")&&this.src){this._loadImage(this.src);return}if(!this._image)return;[...r.keys()].some(t=>W.has(t))&&this._scheduleRender()}disconnectedCallback(){var r;super.disconnectedCallback(),(r=this._observer)==null||r.disconnect(),this._revokeSnapshot()}_loadImage(r){const a=new Image;a.crossOrigin="anonymous",a.onload=()=>{this._image=a,this._scheduleRender()},a.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${r}`)},a.src=r}_scheduleRender(){this._visible?T(()=>this._renderEffect()):this._needsRender=!0}async _renderEffect(){var _;if(!this._image)return;const r=U(this.effect);if(!r){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}const a=Math.min(window.devicePixelRatio||1,G),t=this._image.naturalWidth,i=this._image.naturalHeight,n=document.createElement("canvas");n.width=t*a,n.height=i*a;const o=k(n);if(!o){this._webglAvailable=!1;return}try{const d=w(o,r.vertexShader,r.fragmentShader);o.useProgram(d.program);const m=L(o,this._image),f=P(o,d);o.viewport(0,0,n.width,n.height),o.clearColor(0,0,0,0),o.clear(o.COLOR_BUFFER_BIT),o.activeTexture(o.TEXTURE0),o.bindTexture(o.TEXTURE_2D,m.texture);const c=d.uniformLocations.get("u_image");c&&o.uniform1i(c,0),D(o,d,this._getUniformValues(m,a)),o.bindBuffer(o.ARRAY_BUFFER,f);const h=4*Float32Array.BYTES_PER_ELEMENT,g=d.attribLocations.get("a_position");g!==void 0&&g!==-1&&(o.enableVertexAttribArray(g),o.vertexAttribPointer(g,2,o.FLOAT,!1,h,0));const b=d.attribLocations.get("a_texCoord");b!==void 0&&b!==-1&&(o.enableVertexAttribArray(b),o.vertexAttribPointer(b,2,o.FLOAT,!1,h,2*Float32Array.BYTES_PER_ELEMENT)),V(o);const x=await new Promise(A=>n.toBlob(A));o.deleteTexture(m.texture),o.deleteProgram(d.program),o.deleteBuffer(f),x&&(this._revokeSnapshot(),this._snapshotUrl=URL.createObjectURL(x))}finally{(_=o.getExtension("WEBGL_lose_context"))==null||_.loseContext()}}_revokeSnapshot(){this._snapshotUrl&&(URL.revokeObjectURL(this._snapshotUrl),this._snapshotUrl="")}_getUniformValues(r,a){const t={};return t.u_resolution=[r.width*a,r.height*a],t.u_dotRadius=this.dotRadius,t.u_gridSize=this.gridSize,this.effect==="halftone-cmyk"?(t.u_angleC=this.angleC,t.u_angleM=this.angleM,t.u_angleY=this.angleY,t.u_angleK=this.angleK):this.effect==="halftone-duotone"?(t.u_duotoneColor=this._parseHexColor(this.duotoneColor),t.u_angle=this.angle):this.effect==="pixel-sort"?(t.u_threshold=this.threshold,t.u_direction=this.sortDirection,t.u_span=this.sortSpan):this.effect==="dot-grid"&&(t.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],t.u_bgColor=this._parseHexColor(this.bgColor)),t}_parseHexColor(r){const a=r.replace("#",""),t=parseInt(a.substring(0,2),16)/255,i=parseInt(a.substring(2,4),16)/255,n=parseInt(a.substring(4,6),16)/255;return[t,i,n]}};R.styles=v.css`
215
215
  :host {
216
216
  display: block;
217
217
  position: relative;
218
218
  overflow: hidden;
219
219
  }
220
- canvas, img {
220
+ img {
221
221
  display: block;
222
222
  width: 100%;
223
223
  height: auto;
224
224
  }
225
- `;let i=p;u([s.property()],i.prototype,"src");u([s.property()],i.prototype,"effect");u([s.property({type:Number,attribute:"dot-radius"})],i.prototype,"dotRadius");u([s.property({type:Number,attribute:"grid-size"})],i.prototype,"gridSize");u([s.property({type:Number,attribute:"angle-c"})],i.prototype,"angleC");u([s.property({type:Number,attribute:"angle-m"})],i.prototype,"angleM");u([s.property({type:Number,attribute:"angle-y"})],i.prototype,"angleY");u([s.property({type:Number,attribute:"angle-k"})],i.prototype,"angleK");u([s.property({attribute:"duotone-color"})],i.prototype,"duotoneColor");u([s.property({type:Number})],i.prototype,"angle");u([s.property({type:Number})],i.prototype,"threshold");u([s.property({type:Number,attribute:"sort-direction"})],i.prototype,"sortDirection");u([s.property({type:Number,attribute:"sort-span"})],i.prototype,"sortSpan");u([s.property({type:Number,attribute:"dot-offset-x"})],i.prototype,"dotOffsetX");u([s.property({type:Number,attribute:"dot-offset-y"})],i.prototype,"dotOffsetY");u([s.property({attribute:"bg-color"})],i.prototype,"bgColor");u([s.state()],i.prototype,"_webglAvailable");customElements.get("some-shade-image")||customElements.define("some-shade-image",i);exports.SomeShadeImage=i;exports.get=y;exports.list=V;exports.register=c;
225
+ `;let s=R;l([u.property()],s.prototype,"src");l([u.property()],s.prototype,"effect");l([u.property({type:Number,attribute:"dot-radius"})],s.prototype,"dotRadius");l([u.property({type:Number,attribute:"grid-size"})],s.prototype,"gridSize");l([u.property({type:Number,attribute:"angle-c"})],s.prototype,"angleC");l([u.property({type:Number,attribute:"angle-m"})],s.prototype,"angleM");l([u.property({type:Number,attribute:"angle-y"})],s.prototype,"angleY");l([u.property({type:Number,attribute:"angle-k"})],s.prototype,"angleK");l([u.property({attribute:"duotone-color"})],s.prototype,"duotoneColor");l([u.property({type:Number})],s.prototype,"angle");l([u.property({type:Number})],s.prototype,"threshold");l([u.property({type:Number,attribute:"sort-direction"})],s.prototype,"sortDirection");l([u.property({type:Number,attribute:"sort-span"})],s.prototype,"sortSpan");l([u.property({type:Number,attribute:"dot-offset-x"})],s.prototype,"dotOffsetX");l([u.property({type:Number,attribute:"dot-offset-y"})],s.prototype,"dotOffsetY");l([u.property({attribute:"bg-color"})],s.prototype,"bgColor");l([u.state()],s.prototype,"_webglAvailable");l([u.state()],s.prototype,"_snapshotUrl");customElements.get("some-shade-image")||customElements.define("some-shade-image",s);exports.SomeShadeImage=s;exports.get=U;exports.list=K;exports.register=p;
@@ -1,72 +1,72 @@
1
- import { LitElement as E, css as C, html as v } from "lit";
2
- import { property as u, state as R } from "lit/decorators.js";
3
- function S(t) {
4
- return t.getContext("webgl", {
1
+ import { LitElement as k, css as w, html as x } from "lit";
2
+ import { property as l, state as U } from "lit/decorators.js";
3
+ function D(e) {
4
+ return e.getContext("webgl", {
5
5
  alpha: !0,
6
6
  premultipliedAlpha: !1,
7
7
  preserveDrawingBuffer: !0
8
8
  });
9
9
  }
10
- function b(t, e, o) {
11
- const a = t.createShader(e);
12
- if (!a) throw new Error("Failed to create shader");
13
- if (t.shaderSource(a, o), t.compileShader(a), !t.getShaderParameter(a, t.COMPILE_STATUS)) {
14
- const n = t.getShaderInfoLog(a);
15
- throw t.deleteShader(a), new Error(`Shader compile error: ${n}`);
10
+ function C(e, o, a) {
11
+ const t = e.createShader(o);
12
+ if (!t) throw new Error("Failed to create shader");
13
+ if (e.shaderSource(t, a), e.compileShader(t), !e.getShaderParameter(t, e.COMPILE_STATUS)) {
14
+ const i = e.getShaderInfoLog(t);
15
+ throw e.deleteShader(t), new Error(`Shader compile error: ${i}`);
16
16
  }
17
- return a;
17
+ return t;
18
18
  }
19
- function T(t, e, o) {
20
- const a = b(t, t.VERTEX_SHADER, e), n = b(t, t.FRAGMENT_SHADER, o), r = t.createProgram();
19
+ function L(e, o, a) {
20
+ const t = C(e, e.VERTEX_SHADER, o), i = C(e, e.FRAGMENT_SHADER, a), r = e.createProgram();
21
21
  if (!r) throw new Error("Failed to create program");
22
- if (t.attachShader(r, a), t.attachShader(r, n), t.linkProgram(r), !t.getProgramParameter(r, t.LINK_STATUS)) {
23
- const l = t.getProgramInfoLog(r);
24
- throw t.deleteProgram(r), new Error(`Program link error: ${l}`);
22
+ if (e.attachShader(r, t), e.attachShader(r, i), e.linkProgram(r), !e.getProgramParameter(r, e.LINK_STATUS)) {
23
+ const f = e.getProgramInfoLog(r);
24
+ throw e.deleteProgram(r), new Error(`Program link error: ${f}`);
25
25
  }
26
- t.deleteShader(a), t.deleteShader(n);
27
- const f = /* @__PURE__ */ new Map(), x = t.getProgramParameter(r, t.ACTIVE_ATTRIBUTES);
28
- for (let l = 0; l < x; l++) {
29
- const d = t.getActiveAttrib(r, l);
30
- d && f.set(d.name, t.getAttribLocation(r, d.name));
26
+ e.deleteShader(t), e.deleteShader(i);
27
+ const n = /* @__PURE__ */ new Map(), _ = e.getProgramParameter(r, e.ACTIVE_ATTRIBUTES);
28
+ for (let f = 0; f < _; f++) {
29
+ const c = e.getActiveAttrib(r, f);
30
+ c && n.set(c.name, e.getAttribLocation(r, c.name));
31
31
  }
32
- const g = /* @__PURE__ */ new Map(), y = t.getProgramParameter(r, t.ACTIVE_UNIFORMS);
33
- for (let l = 0; l < y; l++) {
34
- const d = t.getActiveUniform(r, l);
35
- if (d) {
36
- const p = t.getUniformLocation(r, d.name);
37
- p && g.set(d.name, p);
32
+ const d = /* @__PURE__ */ new Map(), m = e.getProgramParameter(r, e.ACTIVE_UNIFORMS);
33
+ for (let f = 0; f < m; f++) {
34
+ const c = e.getActiveUniform(r, f);
35
+ if (c) {
36
+ const h = e.getUniformLocation(r, c.name);
37
+ h && d.set(c.name, h);
38
38
  }
39
39
  }
40
- return { program: r, attribLocations: f, uniformLocations: g };
40
+ return { program: r, attribLocations: n, uniformLocations: d };
41
41
  }
42
- function A(t, e, o) {
43
- for (const [a, n] of Object.entries(o)) {
44
- const r = e.uniformLocations.get(a);
42
+ function P(e, o, a) {
43
+ for (const [t, i] of Object.entries(a)) {
44
+ const r = o.uniformLocations.get(t);
45
45
  if (r) {
46
- if (typeof n == "number")
47
- t.uniform1f(r, n);
48
- else if (Array.isArray(n))
49
- switch (n.length) {
46
+ if (typeof i == "number")
47
+ e.uniform1f(r, i);
48
+ else if (Array.isArray(i))
49
+ switch (i.length) {
50
50
  case 2:
51
- t.uniform2fv(r, n);
51
+ e.uniform2fv(r, i);
52
52
  break;
53
53
  case 3:
54
- t.uniform3fv(r, n);
54
+ e.uniform3fv(r, i);
55
55
  break;
56
56
  case 4:
57
- t.uniform4fv(r, n);
57
+ e.uniform4fv(r, i);
58
58
  break;
59
59
  }
60
60
  }
61
61
  }
62
62
  }
63
- function w(t, e) {
64
- const o = t.createTexture();
65
- if (!o) throw new Error("Failed to create texture");
66
- return t.bindTexture(t.TEXTURE_2D, o), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, e), 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), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.LINEAR), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.LINEAR), { texture: o, width: e.naturalWidth, height: e.naturalHeight };
63
+ function V(e, o) {
64
+ const a = e.createTexture();
65
+ if (!a) throw new Error("Failed to create texture");
66
+ return e.bindTexture(e.TEXTURE_2D, a), e.texImage2D(e.TEXTURE_2D, 0, e.RGBA, e.RGBA, e.UNSIGNED_BYTE, o), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_S, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_WRAP_T, e.CLAMP_TO_EDGE), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MIN_FILTER, e.LINEAR), e.texParameteri(e.TEXTURE_2D, e.TEXTURE_MAG_FILTER, e.LINEAR), { texture: a, width: o.naturalWidth, height: o.naturalHeight };
67
67
  }
68
- function I(t, e) {
69
- const o = new Float32Array([
68
+ function O(e, o) {
69
+ const a = new Float32Array([
70
70
  // pos.x pos.y tex.s tex.t
71
71
  -1,
72
72
  -1,
@@ -84,18 +84,18 @@ function I(t, e) {
84
84
  1,
85
85
  1,
86
86
  0
87
- ]), a = t.createBuffer();
88
- if (!a) throw new Error("Failed to create buffer");
89
- t.bindBuffer(t.ARRAY_BUFFER, a), t.bufferData(t.ARRAY_BUFFER, o, t.STATIC_DRAW);
90
- const n = 4 * Float32Array.BYTES_PER_ELEMENT, r = e.attribLocations.get("a_position");
91
- r !== void 0 && r !== -1 && (t.enableVertexAttribArray(r), t.vertexAttribPointer(r, 2, t.FLOAT, !1, n, 0));
92
- const f = e.attribLocations.get("a_texCoord");
93
- return f !== void 0 && f !== -1 && (t.enableVertexAttribArray(f), t.vertexAttribPointer(f, 2, t.FLOAT, !1, n, 2 * Float32Array.BYTES_PER_ELEMENT)), a;
87
+ ]), t = e.createBuffer();
88
+ if (!t) throw new Error("Failed to create buffer");
89
+ e.bindBuffer(e.ARRAY_BUFFER, t), e.bufferData(e.ARRAY_BUFFER, a, e.STATIC_DRAW);
90
+ const i = 4 * Float32Array.BYTES_PER_ELEMENT, r = o.attribLocations.get("a_position");
91
+ r !== void 0 && r !== -1 && (e.enableVertexAttribArray(r), e.vertexAttribPointer(r, 2, e.FLOAT, !1, i, 0));
92
+ const n = o.attribLocations.get("a_texCoord");
93
+ return n !== void 0 && n !== -1 && (e.enableVertexAttribArray(n), e.vertexAttribPointer(n, 2, e.FLOAT, !1, i, 2 * Float32Array.BYTES_PER_ELEMENT)), t;
94
94
  }
95
- function U(t) {
96
- t.drawArrays(t.TRIANGLE_STRIP, 0, 4);
95
+ function F(e) {
96
+ e.drawArrays(e.TRIANGLE_STRIP, 0, 4);
97
97
  }
98
- const k = `precision mediump float;
98
+ const z = `precision mediump float;
99
99
 
100
100
  varying vec2 v_texCoord;
101
101
 
@@ -151,7 +151,7 @@ void main() {
151
151
 
152
152
  gl_FragColor = vec4(outR, outG, outB, color.a);
153
153
  }
154
- `, c = `attribute vec2 a_position;
154
+ `, b = `attribute vec2 a_position;
155
155
  attribute vec2 a_texCoord;
156
156
  varying vec2 v_texCoord;
157
157
 
@@ -159,10 +159,10 @@ void main() {
159
159
  gl_Position = vec4(a_position, 0.0, 1.0);
160
160
  v_texCoord = a_texCoord;
161
161
  }
162
- `, D = {
162
+ `, M = {
163
163
  name: "halftone-cmyk",
164
- fragmentShader: k,
165
- vertexShader: c,
164
+ fragmentShader: z,
165
+ vertexShader: b,
166
166
  uniforms: [
167
167
  { name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
168
168
  { name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
@@ -171,7 +171,7 @@ void main() {
171
171
  { name: "u_angleY", type: "float", default: 0, attribute: "angle-y" },
172
172
  { name: "u_angleK", type: "float", default: 45, attribute: "angle-k" }
173
173
  ]
174
- }, P = `precision mediump float;
174
+ }, N = `precision mediump float;
175
175
 
176
176
  varying vec2 v_texCoord;
177
177
 
@@ -206,17 +206,17 @@ void main() {
206
206
 
207
207
  gl_FragColor = vec4(result, color.a);
208
208
  }
209
- `, L = {
209
+ `, B = {
210
210
  name: "halftone-duotone",
211
- fragmentShader: P,
212
- vertexShader: c,
211
+ fragmentShader: N,
212
+ vertexShader: b,
213
213
  uniforms: [
214
214
  { name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
215
215
  { name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
216
216
  { name: "u_duotoneColor", type: "vec3", default: [0, 0.6, 0.8], attribute: "duotone-color" },
217
217
  { name: "u_angle", type: "float", default: 0, attribute: "angle" }
218
218
  ]
219
- }, z = `precision mediump float;
219
+ }, I = `precision mediump float;
220
220
 
221
221
  varying vec2 v_texCoord;
222
222
 
@@ -285,16 +285,16 @@ void main() {
285
285
  vec2 sortedUV = spanStartUV + step * float(rank);
286
286
  gl_FragColor = texture2D(u_image, sortedUV);
287
287
  }
288
- `, F = {
288
+ `, Y = {
289
289
  name: "pixel-sort",
290
- fragmentShader: z,
291
- vertexShader: c,
290
+ fragmentShader: I,
291
+ vertexShader: b,
292
292
  uniforms: [
293
293
  { name: "u_threshold", type: "float", default: 0.5, attribute: "threshold" },
294
294
  { name: "u_direction", type: "float", default: 0, attribute: "sort-direction" },
295
295
  { name: "u_span", type: "float", default: 64, attribute: "sort-span" }
296
296
  ]
297
- }, V = `precision mediump float;
297
+ }, K = `precision mediump float;
298
298
 
299
299
  varying vec2 v_texCoord;
300
300
 
@@ -339,190 +339,247 @@ void main() {
339
339
 
340
340
  gl_FragColor = vec4(result, 1.0);
341
341
  }
342
- `, O = {
342
+ `, X = {
343
343
  name: "dot-grid",
344
- fragmentShader: V,
345
- vertexShader: c,
344
+ fragmentShader: K,
345
+ vertexShader: b,
346
346
  uniforms: [
347
347
  { name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
348
348
  { name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
349
349
  { name: "u_dotOffset", type: "vec2", default: [0.5, 0.5], attribute: "dot-offset" },
350
350
  { name: "u_bgColor", type: "vec3", default: [1, 1, 1], attribute: "bg-color" }
351
351
  ]
352
- }, h = /* @__PURE__ */ new Map();
353
- function _(t) {
354
- h.set(t.name, t);
352
+ }, y = /* @__PURE__ */ new Map();
353
+ function v(e) {
354
+ y.set(e.name, e);
355
355
  }
356
- function B(t) {
357
- return h.get(t);
356
+ function G(e) {
357
+ return y.get(e);
358
358
  }
359
- function Y() {
360
- return Array.from(h.keys());
359
+ function Q() {
360
+ return Array.from(y.keys());
361
361
  }
362
- _(D);
363
- _(L);
364
- _(F);
365
- _(O);
366
- var N = Object.defineProperty, s = (t, e, o, a) => {
367
- for (var n = void 0, r = t.length - 1, f; r >= 0; r--)
368
- (f = t[r]) && (n = f(e, o, n) || n);
369
- return n && N(e, o, n), n;
362
+ v(M);
363
+ v(B);
364
+ v(Y);
365
+ v(X);
366
+ var W = Object.defineProperty, u = (e, o, a, t) => {
367
+ for (var i = void 0, r = e.length - 1, n; r >= 0; r--)
368
+ (n = e[r]) && (i = n(o, a, i) || i);
369
+ return i && W(o, a, i), i;
370
370
  };
371
- const m = class m extends E {
371
+ const $ = 2;
372
+ let S = Promise.resolve();
373
+ function T(e) {
374
+ const o = S.then(e, e);
375
+ return S = o, o;
376
+ }
377
+ const H = /* @__PURE__ */ new Set([
378
+ "effect",
379
+ "dotRadius",
380
+ "gridSize",
381
+ "angleC",
382
+ "angleM",
383
+ "angleY",
384
+ "angleK",
385
+ "duotoneColor",
386
+ "angle",
387
+ "threshold",
388
+ "sortDirection",
389
+ "sortSpan",
390
+ "dotOffsetX",
391
+ "dotOffsetY",
392
+ "bgColor"
393
+ ]), E = class E extends k {
372
394
  constructor() {
373
- super(...arguments), this.src = "", this.effect = "halftone-cmyk", this.dotRadius = 4, this.gridSize = 8, this.angleC = 15, this.angleM = 75, this.angleY = 0, this.angleK = 45, this.duotoneColor = "#0099cc", this.angle = 0, this.threshold = 0.5, this.sortDirection = 0, this.sortSpan = 64, this.dotOffsetX = 0.5, this.dotOffsetY = 0.5, this.bgColor = "#ffffff", this._webglAvailable = !0, this._canvas = null, this._gl = null, this._programInfo = null, this._textureInfo = null, this._quadBuffer = null, this._currentEffect = null, this._image = null, this._resizeObserver = null;
395
+ super(...arguments), this.src = "", this.effect = "halftone-cmyk", this.dotRadius = 4, this.gridSize = 8, this.angleC = 15, this.angleM = 75, this.angleY = 0, this.angleK = 45, this.duotoneColor = "#0099cc", this.angle = 0, this.threshold = 0.5, this.sortDirection = 0, this.sortSpan = 64, this.dotOffsetX = 0.5, this.dotOffsetY = 0.5, this.bgColor = "#ffffff", this._webglAvailable = !0, this._snapshotUrl = "", this._image = null, this._observer = null, this._visible = !1, this._needsRender = !1;
374
396
  }
375
397
  render() {
376
- return this._webglAvailable ? v`<canvas></canvas>` : v`<img .src=${this.src} alt="" />`;
398
+ return this._webglAvailable ? x`<img src=${this._snapshotUrl || this.src} alt="" />` : x`<img src=${this.src} alt="" />`;
377
399
  }
378
- firstUpdated() {
379
- if (this._webglAvailable && (this._canvas = this.shadowRoot.querySelector("canvas"), !!this._canvas)) {
380
- if (this._gl = S(this._canvas), !this._gl) {
381
- this._webglAvailable = !1, this.classList.add("webgl-unavailable");
382
- return;
383
- }
384
- this._resizeObserver = new ResizeObserver(() => this._handleResize()), this._resizeObserver.observe(this), this.src && this._loadImage(this.src);
385
- }
400
+ connectedCallback() {
401
+ super.connectedCallback(), this._observer = new IntersectionObserver(
402
+ (o) => {
403
+ var t;
404
+ const a = this._visible;
405
+ this._visible = ((t = o[0]) == null ? void 0 : t.isIntersecting) ?? !1, this._visible && !a && this._needsRender && (this._needsRender = !1, T(() => this._renderEffect()));
406
+ },
407
+ // Start rendering slightly before the element scrolls into view.
408
+ { rootMargin: "200px" }
409
+ ), this._observer.observe(this);
386
410
  }
387
- updated(e) {
388
- if (this._gl) {
389
- if (e.has("src") && this.src) {
390
- this._loadImage(this.src);
391
- return;
392
- }
393
- if (e.has("effect")) {
394
- this._setupProgram(), this._renderFrame();
395
- return;
396
- }
397
- this._renderFrame();
411
+ updated(o) {
412
+ if (o.has("src") && this.src) {
413
+ this._loadImage(this.src);
414
+ return;
398
415
  }
416
+ if (!this._image) return;
417
+ [...o.keys()].some(
418
+ (t) => H.has(t)
419
+ ) && this._scheduleRender();
399
420
  }
400
421
  disconnectedCallback() {
401
- var e;
402
- super.disconnectedCallback(), (e = this._resizeObserver) == null || e.disconnect(), this._cleanup();
403
- }
404
- _loadImage(e) {
405
- const o = new Image();
406
- o.crossOrigin = "anonymous", o.onload = () => {
407
- this._image = o, this._uploadTexture(), this._sizeCanvas(), this._setupProgram(), this._renderFrame();
408
- }, o.onerror = () => {
409
- console.warn(`[some-shade] Failed to load image: ${e}`);
410
- }, o.src = e;
422
+ var o;
423
+ super.disconnectedCallback(), (o = this._observer) == null || o.disconnect(), this._revokeSnapshot();
411
424
  }
412
- _uploadTexture() {
413
- !this._gl || !this._image || (this._textureInfo && this._gl.deleteTexture(this._textureInfo.texture), this._textureInfo = w(this._gl, this._image));
425
+ // ---------------------------------------------------------------------------
426
+ // Image loading
427
+ // ---------------------------------------------------------------------------
428
+ _loadImage(o) {
429
+ const a = new Image();
430
+ a.crossOrigin = "anonymous", a.onload = () => {
431
+ this._image = a, this._scheduleRender();
432
+ }, a.onerror = () => {
433
+ console.warn(`[some-shade] Failed to load image: ${o}`);
434
+ }, a.src = o;
414
435
  }
415
- _sizeCanvas() {
416
- if (!this._canvas || !this._textureInfo) return;
417
- const e = window.devicePixelRatio || 1, o = this._textureInfo.width, a = this._textureInfo.height;
418
- this._canvas.width = o * e, this._canvas.height = a * e, this._canvas.style.aspectRatio = `${o} / ${a}`;
436
+ // ---------------------------------------------------------------------------
437
+ // Render scheduling
438
+ // ---------------------------------------------------------------------------
439
+ _scheduleRender() {
440
+ this._visible ? T(() => this._renderEffect()) : this._needsRender = !0;
419
441
  }
420
- _handleResize() {
421
- this._renderFrame();
422
- }
423
- _setupProgram() {
424
- if (!this._gl) return;
425
- const e = B(this.effect);
426
- if (!e) {
442
+ // ---------------------------------------------------------------------------
443
+ // WebGL render → snapshot → tear-down
444
+ // ---------------------------------------------------------------------------
445
+ async _renderEffect() {
446
+ var _;
447
+ if (!this._image) return;
448
+ const o = G(this.effect);
449
+ if (!o) {
427
450
  console.warn(`[some-shade] Unknown effect: ${this.effect}`);
428
451
  return;
429
452
  }
430
- this._programInfo && this._gl.deleteProgram(this._programInfo.program), this._currentEffect = e, this._programInfo = T(this._gl, e.vertexShader, e.fragmentShader), this._quadBuffer && this._gl.deleteBuffer(this._quadBuffer), this._gl.useProgram(this._programInfo.program), this._quadBuffer = I(this._gl, this._programInfo);
431
- }
432
- _getUniformValues() {
433
- const e = {};
434
- return this._textureInfo && (e.u_resolution = [
435
- this._textureInfo.width * (window.devicePixelRatio || 1),
436
- this._textureInfo.height * (window.devicePixelRatio || 1)
437
- ], e.u_dotRadius = this.dotRadius, e.u_gridSize = this.gridSize, this.effect === "halftone-cmyk" ? (e.u_angleC = this.angleC, e.u_angleM = this.angleM, e.u_angleY = this.angleY, e.u_angleK = this.angleK) : this.effect === "halftone-duotone" ? (e.u_duotoneColor = this._parseHexColor(this.duotoneColor), e.u_angle = this.angle) : this.effect === "pixel-sort" ? (e.u_threshold = this.threshold, e.u_direction = this.sortDirection, e.u_span = this.sortSpan) : this.effect === "dot-grid" && (e.u_dotOffset = [this.dotOffsetX, this.dotOffsetY], e.u_bgColor = this._parseHexColor(this.bgColor))), e;
453
+ const a = Math.min(window.devicePixelRatio || 1, $), t = this._image.naturalWidth, i = this._image.naturalHeight, r = document.createElement("canvas");
454
+ r.width = t * a, r.height = i * a;
455
+ const n = D(r);
456
+ if (!n) {
457
+ this._webglAvailable = !1;
458
+ return;
459
+ }
460
+ try {
461
+ const d = L(
462
+ n,
463
+ o.vertexShader,
464
+ o.fragmentShader
465
+ );
466
+ n.useProgram(d.program);
467
+ const m = V(n, this._image), f = O(n, d);
468
+ n.viewport(0, 0, r.width, r.height), n.clearColor(0, 0, 0, 0), n.clear(n.COLOR_BUFFER_BIT), n.activeTexture(n.TEXTURE0), n.bindTexture(n.TEXTURE_2D, m.texture);
469
+ const c = d.uniformLocations.get("u_image");
470
+ c && n.uniform1i(c, 0), P(
471
+ n,
472
+ d,
473
+ this._getUniformValues(m, a)
474
+ ), n.bindBuffer(n.ARRAY_BUFFER, f);
475
+ const h = 4 * Float32Array.BYTES_PER_ELEMENT, p = d.attribLocations.get("a_position");
476
+ p !== void 0 && p !== -1 && (n.enableVertexAttribArray(p), n.vertexAttribPointer(p, 2, n.FLOAT, !1, h, 0));
477
+ const g = d.attribLocations.get("a_texCoord");
478
+ g !== void 0 && g !== -1 && (n.enableVertexAttribArray(g), n.vertexAttribPointer(
479
+ g,
480
+ 2,
481
+ n.FLOAT,
482
+ !1,
483
+ h,
484
+ 2 * Float32Array.BYTES_PER_ELEMENT
485
+ )), F(n);
486
+ const R = await new Promise(
487
+ (A) => r.toBlob(A)
488
+ );
489
+ n.deleteTexture(m.texture), n.deleteProgram(d.program), n.deleteBuffer(f), R && (this._revokeSnapshot(), this._snapshotUrl = URL.createObjectURL(R));
490
+ } finally {
491
+ (_ = n.getExtension("WEBGL_lose_context")) == null || _.loseContext();
492
+ }
438
493
  }
439
- _parseHexColor(e) {
440
- const o = e.replace("#", ""), a = parseInt(o.substring(0, 2), 16) / 255, n = parseInt(o.substring(2, 4), 16) / 255, r = parseInt(o.substring(4, 6), 16) / 255;
441
- return [a, n, r];
494
+ // ---------------------------------------------------------------------------
495
+ // Helpers
496
+ // ---------------------------------------------------------------------------
497
+ _revokeSnapshot() {
498
+ this._snapshotUrl && (URL.revokeObjectURL(this._snapshotUrl), this._snapshotUrl = "");
442
499
  }
443
- _renderFrame() {
444
- const e = this._gl;
445
- if (!e || !this._programInfo || !this._textureInfo || !this._canvas) return;
446
- e.viewport(0, 0, this._canvas.width, this._canvas.height), e.clearColor(0, 0, 0, 0), e.clear(e.COLOR_BUFFER_BIT), e.useProgram(this._programInfo.program), e.activeTexture(e.TEXTURE0), e.bindTexture(e.TEXTURE_2D, this._textureInfo.texture);
447
- const o = this._programInfo.uniformLocations.get("u_image");
448
- o && e.uniform1i(o, 0), A(e, this._programInfo, this._getUniformValues()), e.bindBuffer(e.ARRAY_BUFFER, this._quadBuffer);
449
- const a = 4 * Float32Array.BYTES_PER_ELEMENT, n = this._programInfo.attribLocations.get("a_position");
450
- n !== void 0 && n !== -1 && (e.enableVertexAttribArray(n), e.vertexAttribPointer(n, 2, e.FLOAT, !1, a, 0));
451
- const r = this._programInfo.attribLocations.get("a_texCoord");
452
- r !== void 0 && r !== -1 && (e.enableVertexAttribArray(r), e.vertexAttribPointer(r, 2, e.FLOAT, !1, a, 2 * Float32Array.BYTES_PER_ELEMENT)), U(e);
500
+ _getUniformValues(o, a) {
501
+ const t = {};
502
+ return t.u_resolution = [
503
+ o.width * a,
504
+ o.height * a
505
+ ], t.u_dotRadius = this.dotRadius, t.u_gridSize = this.gridSize, this.effect === "halftone-cmyk" ? (t.u_angleC = this.angleC, t.u_angleM = this.angleM, t.u_angleY = this.angleY, t.u_angleK = this.angleK) : this.effect === "halftone-duotone" ? (t.u_duotoneColor = this._parseHexColor(this.duotoneColor), t.u_angle = this.angle) : this.effect === "pixel-sort" ? (t.u_threshold = this.threshold, t.u_direction = this.sortDirection, t.u_span = this.sortSpan) : this.effect === "dot-grid" && (t.u_dotOffset = [this.dotOffsetX, this.dotOffsetY], t.u_bgColor = this._parseHexColor(this.bgColor)), t;
453
506
  }
454
- _cleanup() {
455
- this._gl && (this._textureInfo && this._gl.deleteTexture(this._textureInfo.texture), this._programInfo && this._gl.deleteProgram(this._programInfo.program), this._quadBuffer && this._gl.deleteBuffer(this._quadBuffer), this._gl = null, this._programInfo = null, this._textureInfo = null, this._quadBuffer = null);
507
+ _parseHexColor(o) {
508
+ const a = o.replace("#", ""), t = parseInt(a.substring(0, 2), 16) / 255, i = parseInt(a.substring(2, 4), 16) / 255, r = parseInt(a.substring(4, 6), 16) / 255;
509
+ return [t, i, r];
456
510
  }
457
511
  };
458
- m.styles = C`
512
+ E.styles = w`
459
513
  :host {
460
514
  display: block;
461
515
  position: relative;
462
516
  overflow: hidden;
463
517
  }
464
- canvas, img {
518
+ img {
465
519
  display: block;
466
520
  width: 100%;
467
521
  height: auto;
468
522
  }
469
523
  `;
470
- let i = m;
471
- s([
472
- u()
473
- ], i.prototype, "src");
474
- s([
475
- u()
476
- ], i.prototype, "effect");
477
- s([
478
- u({ type: Number, attribute: "dot-radius" })
479
- ], i.prototype, "dotRadius");
480
- s([
481
- u({ type: Number, attribute: "grid-size" })
482
- ], i.prototype, "gridSize");
483
- s([
484
- u({ type: Number, attribute: "angle-c" })
485
- ], i.prototype, "angleC");
486
- s([
487
- u({ type: Number, attribute: "angle-m" })
488
- ], i.prototype, "angleM");
489
- s([
490
- u({ type: Number, attribute: "angle-y" })
491
- ], i.prototype, "angleY");
492
- s([
493
- u({ type: Number, attribute: "angle-k" })
494
- ], i.prototype, "angleK");
495
- s([
496
- u({ attribute: "duotone-color" })
497
- ], i.prototype, "duotoneColor");
498
- s([
499
- u({ type: Number })
500
- ], i.prototype, "angle");
501
- s([
502
- u({ type: Number })
503
- ], i.prototype, "threshold");
504
- s([
505
- u({ type: Number, attribute: "sort-direction" })
506
- ], i.prototype, "sortDirection");
507
- s([
508
- u({ type: Number, attribute: "sort-span" })
509
- ], i.prototype, "sortSpan");
510
- s([
511
- u({ type: Number, attribute: "dot-offset-x" })
512
- ], i.prototype, "dotOffsetX");
513
- s([
514
- u({ type: Number, attribute: "dot-offset-y" })
515
- ], i.prototype, "dotOffsetY");
516
- s([
517
- u({ attribute: "bg-color" })
518
- ], i.prototype, "bgColor");
519
- s([
520
- R()
521
- ], i.prototype, "_webglAvailable");
522
- customElements.get("some-shade-image") || customElements.define("some-shade-image", i);
524
+ let s = E;
525
+ u([
526
+ l()
527
+ ], s.prototype, "src");
528
+ u([
529
+ l()
530
+ ], s.prototype, "effect");
531
+ u([
532
+ l({ type: Number, attribute: "dot-radius" })
533
+ ], s.prototype, "dotRadius");
534
+ u([
535
+ l({ type: Number, attribute: "grid-size" })
536
+ ], s.prototype, "gridSize");
537
+ u([
538
+ l({ type: Number, attribute: "angle-c" })
539
+ ], s.prototype, "angleC");
540
+ u([
541
+ l({ type: Number, attribute: "angle-m" })
542
+ ], s.prototype, "angleM");
543
+ u([
544
+ l({ type: Number, attribute: "angle-y" })
545
+ ], s.prototype, "angleY");
546
+ u([
547
+ l({ type: Number, attribute: "angle-k" })
548
+ ], s.prototype, "angleK");
549
+ u([
550
+ l({ attribute: "duotone-color" })
551
+ ], s.prototype, "duotoneColor");
552
+ u([
553
+ l({ type: Number })
554
+ ], s.prototype, "angle");
555
+ u([
556
+ l({ type: Number })
557
+ ], s.prototype, "threshold");
558
+ u([
559
+ l({ type: Number, attribute: "sort-direction" })
560
+ ], s.prototype, "sortDirection");
561
+ u([
562
+ l({ type: Number, attribute: "sort-span" })
563
+ ], s.prototype, "sortSpan");
564
+ u([
565
+ l({ type: Number, attribute: "dot-offset-x" })
566
+ ], s.prototype, "dotOffsetX");
567
+ u([
568
+ l({ type: Number, attribute: "dot-offset-y" })
569
+ ], s.prototype, "dotOffsetY");
570
+ u([
571
+ l({ attribute: "bg-color" })
572
+ ], s.prototype, "bgColor");
573
+ u([
574
+ U()
575
+ ], s.prototype, "_webglAvailable");
576
+ u([
577
+ U()
578
+ ], s.prototype, "_snapshotUrl");
579
+ customElements.get("some-shade-image") || customElements.define("some-shade-image", s);
523
580
  export {
524
- i as SomeShadeImage,
525
- B as get,
526
- Y as list,
527
- _ as register
581
+ s as SomeShadeImage,
582
+ G as get,
583
+ Q as list,
584
+ v as register
528
585
  };
@@ -1,4 +1,4 @@
1
- (function(f,c){typeof exports=="object"&&typeof module<"u"?c(exports,require("lit"),require("lit/decorators.js")):typeof define=="function"&&define.amd?define(["exports","lit","lit/decorators.js"],c):(f=typeof globalThis<"u"?globalThis:f||self,c(f.SomeShade={},f.Lit,f.LitDecorators))})(this,(function(f,c,s){"use strict";function E(t){return t.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function v(t,e,n){const i=t.createShader(e);if(!i)throw new Error("Failed to create shader");if(t.shaderSource(i,n),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS)){const o=t.getShaderInfoLog(i);throw t.deleteShader(i),new Error(`Shader compile error: ${o}`)}return i}function S(t,e,n){const i=v(t,t.VERTEX_SHADER,e),o=v(t,t.FRAGMENT_SHADER,n),r=t.createProgram();if(!r)throw new Error("Failed to create program");if(t.attachShader(r,i),t.attachShader(r,o),t.linkProgram(r),!t.getProgramParameter(r,t.LINK_STATUS)){const d=t.getProgramInfoLog(r);throw t.deleteProgram(r),new Error(`Program link error: ${d}`)}t.deleteShader(i),t.deleteShader(o);const l=new Map,z=t.getProgramParameter(r,t.ACTIVE_ATTRIBUTES);for(let d=0;d<z;d++){const h=t.getActiveAttrib(r,d);h&&l.set(h.name,t.getAttribLocation(r,h.name))}const y=new Map,F=t.getProgramParameter(r,t.ACTIVE_UNIFORMS);for(let d=0;d<F;d++){const h=t.getActiveUniform(r,d);if(h){const x=t.getUniformLocation(r,h.name);x&&y.set(h.name,x)}}return{program:r,attribLocations:l,uniformLocations:y}}function C(t,e,n){for(const[i,o]of Object.entries(n)){const r=e.uniformLocations.get(i);if(r){if(typeof o=="number")t.uniform1f(r,o);else if(Array.isArray(o))switch(o.length){case 2:t.uniform2fv(r,o);break;case 3:t.uniform3fv(r,o);break;case 4:t.uniform4fv(r,o);break}}}}function R(t,e){const n=t.createTexture();if(!n)throw new Error("Failed to create texture");return t.bindTexture(t.TEXTURE_2D,n),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,e),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),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),{texture:n,width:e.naturalWidth,height:e.naturalHeight}}function T(t,e){const n=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),i=t.createBuffer();if(!i)throw new Error("Failed to create buffer");t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,n,t.STATIC_DRAW);const o=4*Float32Array.BYTES_PER_ELEMENT,r=e.attribLocations.get("a_position");r!==void 0&&r!==-1&&(t.enableVertexAttribArray(r),t.vertexAttribPointer(r,2,t.FLOAT,!1,o,0));const l=e.attribLocations.get("a_texCoord");return l!==void 0&&l!==-1&&(t.enableVertexAttribArray(l),t.vertexAttribPointer(l,2,t.FLOAT,!1,o,2*Float32Array.BYTES_PER_ELEMENT)),i}function A(t){t.drawArrays(t.TRIANGLE_STRIP,0,4)}const w=`precision mediump float;
1
+ (function(d,h){typeof exports=="object"&&typeof module<"u"?h(exports,require("lit"),require("lit/decorators.js")):typeof define=="function"&&define.amd?define(["exports","lit","lit/decorators.js"],h):(d=typeof globalThis<"u"?globalThis:d||self,h(d.SomeShade={},d.Lit,d.LitDecorators))})(this,(function(d,h,u){"use strict";function k(e){return e.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function x(e,n,a){const t=e.createShader(n);if(!t)throw new Error("Failed to create shader");if(e.shaderSource(t,a),e.compileShader(t),!e.getShaderParameter(t,e.COMPILE_STATUS)){const i=e.getShaderInfoLog(t);throw e.deleteShader(t),new Error(`Shader compile error: ${i}`)}return t}function w(e,n,a){const t=x(e,e.VERTEX_SHADER,n),i=x(e,e.FRAGMENT_SHADER,a),o=e.createProgram();if(!o)throw new Error("Failed to create program");if(e.attachShader(o,t),e.attachShader(o,i),e.linkProgram(o),!e.getProgramParameter(o,e.LINK_STATUS)){const f=e.getProgramInfoLog(o);throw e.deleteProgram(o),new Error(`Program link error: ${f}`)}e.deleteShader(t),e.deleteShader(i);const r=new Map,v=e.getProgramParameter(o,e.ACTIVE_ATTRIBUTES);for(let f=0;f<v;f++){const m=e.getActiveAttrib(o,f);m&&r.set(m.name,e.getAttribLocation(o,m.name))}const c=new Map,_=e.getProgramParameter(o,e.ACTIVE_UNIFORMS);for(let f=0;f<_;f++){const m=e.getActiveUniform(o,f);if(m){const g=e.getUniformLocation(o,m.name);g&&c.set(m.name,g)}}return{program:o,attribLocations:r,uniformLocations:c}}function D(e,n,a){for(const[t,i]of Object.entries(a)){const o=n.uniformLocations.get(t);if(o){if(typeof i=="number")e.uniform1f(o,i);else if(Array.isArray(i))switch(i.length){case 2:e.uniform2fv(o,i);break;case 3:e.uniform3fv(o,i);break;case 4:e.uniform4fv(o,i);break}}}}function L(e,n){const a=e.createTexture();if(!a)throw new Error("Failed to create texture");return e.bindTexture(e.TEXTURE_2D,a),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,n),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),{texture:a,width:n.naturalWidth,height:n.naturalHeight}}function P(e,n){const a=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),t=e.createBuffer();if(!t)throw new Error("Failed to create buffer");e.bindBuffer(e.ARRAY_BUFFER,t),e.bufferData(e.ARRAY_BUFFER,a,e.STATIC_DRAW);const i=4*Float32Array.BYTES_PER_ELEMENT,o=n.attribLocations.get("a_position");o!==void 0&&o!==-1&&(e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,i,0));const r=n.attribLocations.get("a_texCoord");return r!==void 0&&r!==-1&&(e.enableVertexAttribArray(r),e.vertexAttribPointer(r,2,e.FLOAT,!1,i,2*Float32Array.BYTES_PER_ELEMENT)),t}function V(e){e.drawArrays(e.TRIANGLE_STRIP,0,4)}const O=`precision mediump float;
2
2
 
3
3
  varying vec2 v_texCoord;
4
4
 
@@ -54,7 +54,7 @@ void main() {
54
54
 
55
55
  gl_FragColor = vec4(outR, outG, outB, color.a);
56
56
  }
57
- `,m=`attribute vec2 a_position;
57
+ `,b=`attribute vec2 a_position;
58
58
  attribute vec2 a_texCoord;
59
59
  varying vec2 v_texCoord;
60
60
 
@@ -62,7 +62,7 @@ void main() {
62
62
  gl_Position = vec4(a_position, 0.0, 1.0);
63
63
  v_texCoord = a_texCoord;
64
64
  }
65
- `,I={name:"halftone-cmyk",fragmentShader:w,vertexShader:m,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"}]},U={name:"halftone-duotone",fragmentShader:`precision mediump float;
65
+ `,F={name:"halftone-cmyk",fragmentShader:O,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"}]},z={name:"halftone-duotone",fragmentShader:`precision mediump float;
66
66
 
67
67
  varying vec2 v_texCoord;
68
68
 
@@ -97,7 +97,7 @@ void main() {
97
97
 
98
98
  gl_FragColor = vec4(result, color.a);
99
99
  }
100
- `,vertexShader:m,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},k={name:"pixel-sort",fragmentShader:`precision mediump float;
100
+ `,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},M={name:"pixel-sort",fragmentShader:`precision mediump float;
101
101
 
102
102
  varying vec2 v_texCoord;
103
103
 
@@ -166,7 +166,7 @@ void main() {
166
166
  vec2 sortedUV = spanStartUV + step * float(rank);
167
167
  gl_FragColor = texture2D(u_image, sortedUV);
168
168
  }
169
- `,vertexShader:m,uniforms:[{name:"u_threshold",type:"float",default:.5,attribute:"threshold"},{name:"u_direction",type:"float",default:0,attribute:"sort-direction"},{name:"u_span",type:"float",default:64,attribute:"sort-span"}]},D={name:"dot-grid",fragmentShader:`precision mediump float;
169
+ `,vertexShader:b,uniforms:[{name:"u_threshold",type:"float",default:.5,attribute:"threshold"},{name:"u_direction",type:"float",default:0,attribute:"sort-direction"},{name:"u_span",type:"float",default:64,attribute:"sort-span"}]},I={name:"dot-grid",fragmentShader:`precision mediump float;
170
170
 
171
171
  varying vec2 v_texCoord;
172
172
 
@@ -211,15 +211,15 @@ void main() {
211
211
 
212
212
  gl_FragColor = vec4(result, 1.0);
213
213
  }
214
- `,vertexShader:m,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"}]},p=new Map;function _(t){p.set(t.name,t)}function b(t){return p.get(t)}function P(){return Array.from(p.keys())}_(I),_(U),_(k),_(D);var L=Object.defineProperty,u=(t,e,n,i)=>{for(var o=void 0,r=t.length-1,l;r>=0;r--)(l=t[r])&&(o=l(e,n,o)||o);return o&&L(e,n,o),o};const g=class g extends c.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.duotoneColor="#0099cc",this.angle=0,this.threshold=.5,this.sortDirection=0,this.sortSpan=64,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this._webglAvailable=!0,this._canvas=null,this._gl=null,this._programInfo=null,this._textureInfo=null,this._quadBuffer=null,this._currentEffect=null,this._image=null,this._resizeObserver=null}render(){return this._webglAvailable?c.html`<canvas></canvas>`:c.html`<img .src=${this.src} alt="" />`}firstUpdated(){if(this._webglAvailable&&(this._canvas=this.shadowRoot.querySelector("canvas"),!!this._canvas)){if(this._gl=E(this._canvas),!this._gl){this._webglAvailable=!1,this.classList.add("webgl-unavailable");return}this._resizeObserver=new ResizeObserver(()=>this._handleResize()),this._resizeObserver.observe(this),this.src&&this._loadImage(this.src)}}updated(e){if(this._gl){if(e.has("src")&&this.src){this._loadImage(this.src);return}if(e.has("effect")){this._setupProgram(),this._renderFrame();return}this._renderFrame()}}disconnectedCallback(){var e;super.disconnectedCallback(),(e=this._resizeObserver)==null||e.disconnect(),this._cleanup()}_loadImage(e){const n=new Image;n.crossOrigin="anonymous",n.onload=()=>{this._image=n,this._uploadTexture(),this._sizeCanvas(),this._setupProgram(),this._renderFrame()},n.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${e}`)},n.src=e}_uploadTexture(){!this._gl||!this._image||(this._textureInfo&&this._gl.deleteTexture(this._textureInfo.texture),this._textureInfo=R(this._gl,this._image))}_sizeCanvas(){if(!this._canvas||!this._textureInfo)return;const e=window.devicePixelRatio||1,n=this._textureInfo.width,i=this._textureInfo.height;this._canvas.width=n*e,this._canvas.height=i*e,this._canvas.style.aspectRatio=`${n} / ${i}`}_handleResize(){this._renderFrame()}_setupProgram(){if(!this._gl)return;const e=b(this.effect);if(!e){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}this._programInfo&&this._gl.deleteProgram(this._programInfo.program),this._currentEffect=e,this._programInfo=S(this._gl,e.vertexShader,e.fragmentShader),this._quadBuffer&&this._gl.deleteBuffer(this._quadBuffer),this._gl.useProgram(this._programInfo.program),this._quadBuffer=T(this._gl,this._programInfo)}_getUniformValues(){const e={};return this._textureInfo&&(e.u_resolution=[this._textureInfo.width*(window.devicePixelRatio||1),this._textureInfo.height*(window.devicePixelRatio||1)],e.u_dotRadius=this.dotRadius,e.u_gridSize=this.gridSize,this.effect==="halftone-cmyk"?(e.u_angleC=this.angleC,e.u_angleM=this.angleM,e.u_angleY=this.angleY,e.u_angleK=this.angleK):this.effect==="halftone-duotone"?(e.u_duotoneColor=this._parseHexColor(this.duotoneColor),e.u_angle=this.angle):this.effect==="pixel-sort"?(e.u_threshold=this.threshold,e.u_direction=this.sortDirection,e.u_span=this.sortSpan):this.effect==="dot-grid"&&(e.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],e.u_bgColor=this._parseHexColor(this.bgColor))),e}_parseHexColor(e){const n=e.replace("#",""),i=parseInt(n.substring(0,2),16)/255,o=parseInt(n.substring(2,4),16)/255,r=parseInt(n.substring(4,6),16)/255;return[i,o,r]}_renderFrame(){const e=this._gl;if(!e||!this._programInfo||!this._textureInfo||!this._canvas)return;e.viewport(0,0,this._canvas.width,this._canvas.height),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT),e.useProgram(this._programInfo.program),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this._textureInfo.texture);const n=this._programInfo.uniformLocations.get("u_image");n&&e.uniform1i(n,0),C(e,this._programInfo,this._getUniformValues()),e.bindBuffer(e.ARRAY_BUFFER,this._quadBuffer);const i=4*Float32Array.BYTES_PER_ELEMENT,o=this._programInfo.attribLocations.get("a_position");o!==void 0&&o!==-1&&(e.enableVertexAttribArray(o),e.vertexAttribPointer(o,2,e.FLOAT,!1,i,0));const r=this._programInfo.attribLocations.get("a_texCoord");r!==void 0&&r!==-1&&(e.enableVertexAttribArray(r),e.vertexAttribPointer(r,2,e.FLOAT,!1,i,2*Float32Array.BYTES_PER_ELEMENT)),A(e)}_cleanup(){this._gl&&(this._textureInfo&&this._gl.deleteTexture(this._textureInfo.texture),this._programInfo&&this._gl.deleteProgram(this._programInfo.program),this._quadBuffer&&this._gl.deleteBuffer(this._quadBuffer),this._gl=null,this._programInfo=null,this._textureInfo=null,this._quadBuffer=null)}};g.styles=c.css`
214
+ `,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"}]},R=new Map;function p(e){R.set(e.name,e)}function C(e){return R.get(e)}function N(){return Array.from(R.keys())}p(F),p(z),p(M),p(I);var B=Object.defineProperty,l=(e,n,a,t)=>{for(var i=void 0,o=e.length-1,r;o>=0;o--)(r=e[o])&&(i=r(n,a,i)||i);return i&&B(n,a,i),i};const Y=2;let T=Promise.resolve();function U(e){const n=T.then(e,e);return T=n,n}const K=new Set(["effect","dotRadius","gridSize","angleC","angleM","angleY","angleK","duotoneColor","angle","threshold","sortDirection","sortSpan","dotOffsetX","dotOffsetY","bgColor"]),S=class S extends h.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.duotoneColor="#0099cc",this.angle=0,this.threshold=.5,this.sortDirection=0,this.sortSpan=64,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this._webglAvailable=!0,this._snapshotUrl="",this._image=null,this._observer=null,this._visible=!1,this._needsRender=!1}render(){return this._webglAvailable?h.html`<img src=${this._snapshotUrl||this.src} alt="" />`:h.html`<img src=${this.src} alt="" />`}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(n=>{var t;const a=this._visible;this._visible=((t=n[0])==null?void 0:t.isIntersecting)??!1,this._visible&&!a&&this._needsRender&&(this._needsRender=!1,U(()=>this._renderEffect()))},{rootMargin:"200px"}),this._observer.observe(this)}updated(n){if(n.has("src")&&this.src){this._loadImage(this.src);return}if(!this._image)return;[...n.keys()].some(t=>K.has(t))&&this._scheduleRender()}disconnectedCallback(){var n;super.disconnectedCallback(),(n=this._observer)==null||n.disconnect(),this._revokeSnapshot()}_loadImage(n){const a=new Image;a.crossOrigin="anonymous",a.onload=()=>{this._image=a,this._scheduleRender()},a.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${n}`)},a.src=n}_scheduleRender(){this._visible?U(()=>this._renderEffect()):this._needsRender=!0}async _renderEffect(){var v;if(!this._image)return;const n=C(this.effect);if(!n){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}const a=Math.min(window.devicePixelRatio||1,Y),t=this._image.naturalWidth,i=this._image.naturalHeight,o=document.createElement("canvas");o.width=t*a,o.height=i*a;const r=k(o);if(!r){this._webglAvailable=!1;return}try{const c=w(r,n.vertexShader,n.fragmentShader);r.useProgram(c.program);const _=L(r,this._image),f=P(r,c);r.viewport(0,0,o.width,o.height),r.clearColor(0,0,0,0),r.clear(r.COLOR_BUFFER_BIT),r.activeTexture(r.TEXTURE0),r.bindTexture(r.TEXTURE_2D,_.texture);const m=c.uniformLocations.get("u_image");m&&r.uniform1i(m,0),D(r,c,this._getUniformValues(_,a)),r.bindBuffer(r.ARRAY_BUFFER,f);const g=4*Float32Array.BYTES_PER_ELEMENT,y=c.attribLocations.get("a_position");y!==void 0&&y!==-1&&(r.enableVertexAttribArray(y),r.vertexAttribPointer(y,2,r.FLOAT,!1,g,0));const E=c.attribLocations.get("a_texCoord");E!==void 0&&E!==-1&&(r.enableVertexAttribArray(E),r.vertexAttribPointer(E,2,r.FLOAT,!1,g,2*Float32Array.BYTES_PER_ELEMENT)),V(r);const A=await new Promise(X=>o.toBlob(X));r.deleteTexture(_.texture),r.deleteProgram(c.program),r.deleteBuffer(f),A&&(this._revokeSnapshot(),this._snapshotUrl=URL.createObjectURL(A))}finally{(v=r.getExtension("WEBGL_lose_context"))==null||v.loseContext()}}_revokeSnapshot(){this._snapshotUrl&&(URL.revokeObjectURL(this._snapshotUrl),this._snapshotUrl="")}_getUniformValues(n,a){const t={};return t.u_resolution=[n.width*a,n.height*a],t.u_dotRadius=this.dotRadius,t.u_gridSize=this.gridSize,this.effect==="halftone-cmyk"?(t.u_angleC=this.angleC,t.u_angleM=this.angleM,t.u_angleY=this.angleY,t.u_angleK=this.angleK):this.effect==="halftone-duotone"?(t.u_duotoneColor=this._parseHexColor(this.duotoneColor),t.u_angle=this.angle):this.effect==="pixel-sort"?(t.u_threshold=this.threshold,t.u_direction=this.sortDirection,t.u_span=this.sortSpan):this.effect==="dot-grid"&&(t.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],t.u_bgColor=this._parseHexColor(this.bgColor)),t}_parseHexColor(n){const a=n.replace("#",""),t=parseInt(a.substring(0,2),16)/255,i=parseInt(a.substring(2,4),16)/255,o=parseInt(a.substring(4,6),16)/255;return[t,i,o]}};S.styles=h.css`
215
215
  :host {
216
216
  display: block;
217
217
  position: relative;
218
218
  overflow: hidden;
219
219
  }
220
- canvas, img {
220
+ img {
221
221
  display: block;
222
222
  width: 100%;
223
223
  height: auto;
224
224
  }
225
- `;let a=g;u([s.property()],a.prototype,"src"),u([s.property()],a.prototype,"effect"),u([s.property({type:Number,attribute:"dot-radius"})],a.prototype,"dotRadius"),u([s.property({type:Number,attribute:"grid-size"})],a.prototype,"gridSize"),u([s.property({type:Number,attribute:"angle-c"})],a.prototype,"angleC"),u([s.property({type:Number,attribute:"angle-m"})],a.prototype,"angleM"),u([s.property({type:Number,attribute:"angle-y"})],a.prototype,"angleY"),u([s.property({type:Number,attribute:"angle-k"})],a.prototype,"angleK"),u([s.property({attribute:"duotone-color"})],a.prototype,"duotoneColor"),u([s.property({type:Number})],a.prototype,"angle"),u([s.property({type:Number})],a.prototype,"threshold"),u([s.property({type:Number,attribute:"sort-direction"})],a.prototype,"sortDirection"),u([s.property({type:Number,attribute:"sort-span"})],a.prototype,"sortSpan"),u([s.property({type:Number,attribute:"dot-offset-x"})],a.prototype,"dotOffsetX"),u([s.property({type:Number,attribute:"dot-offset-y"})],a.prototype,"dotOffsetY"),u([s.property({attribute:"bg-color"})],a.prototype,"bgColor"),u([s.state()],a.prototype,"_webglAvailable"),customElements.get("some-shade-image")||customElements.define("some-shade-image",a),f.SomeShadeImage=a,f.get=b,f.list=P,f.register=_,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})}));
225
+ `;let s=S;l([u.property()],s.prototype,"src"),l([u.property()],s.prototype,"effect"),l([u.property({type:Number,attribute:"dot-radius"})],s.prototype,"dotRadius"),l([u.property({type:Number,attribute:"grid-size"})],s.prototype,"gridSize"),l([u.property({type:Number,attribute:"angle-c"})],s.prototype,"angleC"),l([u.property({type:Number,attribute:"angle-m"})],s.prototype,"angleM"),l([u.property({type:Number,attribute:"angle-y"})],s.prototype,"angleY"),l([u.property({type:Number,attribute:"angle-k"})],s.prototype,"angleK"),l([u.property({attribute:"duotone-color"})],s.prototype,"duotoneColor"),l([u.property({type:Number})],s.prototype,"angle"),l([u.property({type:Number})],s.prototype,"threshold"),l([u.property({type:Number,attribute:"sort-direction"})],s.prototype,"sortDirection"),l([u.property({type:Number,attribute:"sort-span"})],s.prototype,"sortSpan"),l([u.property({type:Number,attribute:"dot-offset-x"})],s.prototype,"dotOffsetX"),l([u.property({type:Number,attribute:"dot-offset-y"})],s.prototype,"dotOffsetY"),l([u.property({attribute:"bg-color"})],s.prototype,"bgColor"),l([u.state()],s.prototype,"_webglAvailable"),l([u.state()],s.prototype,"_snapshotUrl"),customElements.get("some-shade-image")||customElements.define("some-shade-image",s),d.SomeShadeImage=s,d.get=C,d.list=N,d.register=p,Object.defineProperty(d,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johnfmorton/some-shade",
3
- "version": "0.1.0-beta.7",
3
+ "version": "0.1.0-beta.8",
4
4
  "license": "ISC",
5
5
  "homepage": "https://johnfmorton.github.io/some-shade-web-component/",
6
6
  "repository": {