UNPKG

favium

Version:

Favium is a lightweight package that allows you to create ICO and PNG formatted favicons from a canvas element.

1 lines 6.04 kB
var e=Object.defineProperty,t=(t,n,r)=>((t,n,r)=>n in t?e(t,n,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[n]=r)(t,n+"",r),n=class{constructor(e){if(t(this,"canvas"),!(e instanceof HTMLCanvasElement))throw new TypeError("Parameter must be an HTMLCanvasElement");this.canvas=e}resize(e,t){if(!Number.isInteger(e)||!Number.isInteger(t))throw new RangeError("Width and height must be integers");if(e<=0||t<=0)throw new RangeError("Width and height must be positive");for(;this.canvas.width/2>=e;)this._resize(this.canvas.width/2,this.canvas.height/2);return this.canvas.width>e&&this._resize(e,t),this.canvas}_resize(e,t){const n=document.createElement("canvas"),r=n.getContext("2d");if(!r)throw new Error("Failed to get 2D context");n.width=e,n.height=t,r.drawImage(this.canvas,0,0,e,t),this.canvas=n}},r=class{constructor(e){if(t(this,"canvas"),!(e instanceof HTMLCanvasElement))throw new TypeError("Parameter must be an HTMLCanvasElement");this.canvas=e}generate(e=[16,32,48]){if(!e.every((e=>Number.isInteger(e)&&e>0&&e<=256)))throw new RangeError("Sizes must be positive integers between 1 and 256");const t=new n(this.canvas).resize(128,128),r=this.createIconDirHeader(e.length);let a="",i="";for(let r=0;r<e.length;r++){const s=e[r],o=new n(t).resize(s,s),h=this.createBitmapInfoHeader(s),c=this.createBitmapImageData(o),l=h.length+c.length,g=6+16*e.length+i.length;a+=this.createIconDirEntry(s,l,g),i+=h+c}return`data:image/x-icon;base64,${btoa(r+a+i)}`}createIconDirHeader(e){const t=new ArrayBuffer(6),n=new DataView(t);return n.setUint16(0,0,!0),n.setUint16(2,1,!0),n.setUint16(4,e,!0),String.fromCharCode(...new Uint8Array(t))}createIconDirEntry(e,t,n){const r=new ArrayBuffer(16),a=new DataView(r);return a.setUint8(0,e),a.setUint8(1,e),a.setUint8(2,0),a.setUint8(3,0),a.setUint16(4,1,!0),a.setUint16(6,32,!0),a.setUint32(8,t,!0),a.setUint32(12,n,!0),String.fromCharCode(...new Uint8Array(r))}createBitmapInfoHeader(e){const t=new ArrayBuffer(40),n=new DataView(t);return n.setUint32(0,40,!0),n.setInt32(4,e,!0),n.setInt32(8,2*e,!0),n.setUint16(12,1,!0),n.setUint16(14,32,!0),n.setUint32(16,0,!0),n.setUint32(20,0,!0),String.fromCharCode(...new Uint8Array(t))}createBitmapImageData(e){const t=e.getContext("2d");if(!t)throw new Error("Failed to get 2D context");const{width:n,height:r}=e,a=t.getImageData(0,0,n,r).data,i=new Uint8ClampedArray(a.length);for(let e=0;e<r;e++)for(let t=0;t<n;t++){const s=4*(e*n+t),o=4*((r-1-e)*n+t);i[o]=a[s+2],i[o+1]=a[s+1],i[o+2]=a[s],i[o+3]=a[s+3]}const s=new Uint8Array(n*r/8).fill(0);return String.fromCharCode(...i,...s)}},a=class{constructor(e){if(t(this,"canvas"),!(e instanceof HTMLCanvasElement))throw new TypeError("Parameter must be an HTMLCanvasElement");this.canvas=e}generate(e){if(!Number.isInteger(e)||e<=0)throw new RangeError("Size must be a positive integer");return new n(this.canvas).resize(e,e).toDataURL()}},i=class{constructor(e){if(t(this,"canvas"),!(e instanceof HTMLCanvasElement))throw new TypeError("Parameter must be an HTMLCanvasElement");this.canvas=e}generate(){const e=new r(this.canvas),t=new a(this.canvas);return{ico:e.generate([16,32,48]),png16:t.generate(16),png32:t.generate(32),png150:t.generate(150),png180:t.generate(180),png192:t.generate(192),png512:t.generate(512)}}},s=class e{constructor(e){if(t(this,"canvas"),!(e instanceof HTMLCanvasElement))throw new TypeError("Parameter must be an HTMLCanvasElement");this.canvas=e}generate(e={}){const t=this.canvas.getContext("2d");if(!t)throw new Error("Failed to get 2D context");const{width:n,height:r,text:a,fontColor:i,fontFamily:s,fontSize:o,fontWeight:h,fontStyle:c,cornerRadius:l,backgroundColor:g}={width:128,height:128,text:"F",fontColor:"white",fontFamily:"Helvetica",fontSize:64,fontWeight:"400",fontStyle:"normal",cornerRadius:0,backgroundColor:"black",...e};if("number"!=typeof n||n<=0)throw new Error("Width must be a positive number");if("number"!=typeof r||r<=0)throw new Error("Height must be a positive number");if("number"!=typeof o||o<=0)throw new Error("Font size must be a positive number");if("number"!=typeof l||l<0)throw new Error("Corner radius must be a non-negative number");if(this.canvas.width=2*n,this.canvas.height=2*r,this.canvas.style.width=`${n}px`,this.canvas.style.height=`${r}px`,t.scale(2,2),this.drawBackground(t,n,r,l,g),a){const e=`${c} ${h} ${o}px ${s}`;t.fillStyle=i,t.font=e,t.textBaseline="alphabetic",t.textAlign="center";const l=this.measureOffsets(t,a,o);t.fillText(a,n/2+l.horizontal,r/2+l.vertical)}return this.canvas}drawBackground(e,t,n,r,a){e.fillStyle=a;const i=Math.min(t,n)/2,s=Math.min(r,i);0===s?e.fillRect(0,0,t,n):(e.beginPath(),e.moveTo(s,0),e.arcTo(t,0,t,n,s),e.arcTo(t,n,0,n,s),e.arcTo(0,n,0,0,s),e.arcTo(0,0,t,0,s),e.closePath(),e.fill())}measureOffsets(e,t,n){const r=document.createElement("canvas"),a=r.getContext("2d");if(!a)throw new Error("Failed to get 2D context");r.width=2*e.measureText(t).width||1,r.height=2*n,a.font=e.font,a.textBaseline="alphabetic",a.textAlign="center",a.fillStyle="white",a.fillText(t,r.width/2,r.height/2);const i=a.getImageData(0,0,r.width,r.height).data;let s,o,h,c;for(let e=0;e<r.height;e++)for(let t=0;t<r.width;t++)if(255===i[4*(e*r.width+t)]){s=void 0===s?e:s,o=e;break}for(let e=0;e<r.width;e++)for(let t=0;t<r.height;t++)if(255===i[4*(t*r.width+e)]){h=void 0===h?e:h,c=e;break}const l=r.height/2,g=r.width/2;return{vertical:l-(void 0!==s&&void 0!==o?s+(o-s)/2:l),horizontal:g-(void 0!==h&&void 0!==c?h+(c-h)/2:g)}}static generate(t={}){const n=document.createElement("canvas");return new e(n).generate(t)}},o=class{constructor(e){if(t(this,"canvas"),!(e instanceof HTMLCanvasElement))throw new TypeError("Parameter must be an HTMLCanvasElement");this.canvas=e}bundle(){return new i(this.canvas).generate()}ico(e=[16,32,48]){return new r(this.canvas).generate(e)}png(e){return new a(this.canvas).generate(e)}resize(e){return new n(this.canvas).resize(e,e)}};export{n as CanvasResize,o as FaviconComposer,r as IcoGenerator,i as ImageBundleGenerator,a as PngGenerator,s as TextIconGenerator};