@tsparticles/shape-image 3.2.2 → 3.4.0

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.
Files changed (46) hide show
  1. package/browser/GifUtils/Enums/DisposalMethod.js +11 -1
  2. package/browser/GifUtils/Types/GIFDataHeaders.js +10 -1
  3. package/browser/GifUtils/Utils.js +19 -17
  4. package/browser/ImageDrawer.js +42 -38
  5. package/browser/ImagePreloader.js +1 -1
  6. package/browser/Utils.js +1 -1
  7. package/browser/index.js +4 -3
  8. package/cjs/GifUtils/Enums/DisposalMethod.js +12 -0
  9. package/cjs/GifUtils/Types/GIFDataHeaders.js +11 -0
  10. package/cjs/GifUtils/Utils.js +20 -41
  11. package/cjs/ImageDrawer.js +43 -62
  12. package/cjs/ImagePreloader.js +1 -1
  13. package/cjs/Utils.js +1 -1
  14. package/cjs/index.js +6 -28
  15. package/esm/GifUtils/Enums/DisposalMethod.js +11 -1
  16. package/esm/GifUtils/Types/GIFDataHeaders.js +10 -1
  17. package/esm/GifUtils/Utils.js +19 -17
  18. package/esm/ImageDrawer.js +42 -38
  19. package/esm/ImagePreloader.js +1 -1
  20. package/esm/Utils.js +1 -1
  21. package/esm/index.js +4 -3
  22. package/package.json +2 -2
  23. package/report.html +1 -1
  24. package/tsparticles.shape.image.js +82 -200
  25. package/tsparticles.shape.image.min.js +1 -1
  26. package/tsparticles.shape.image.min.js.LICENSE.txt +1 -1
  27. package/types/GifUtils/Enums/DisposalMethod.d.ts +1 -1
  28. package/types/GifUtils/Types/GIFDataHeaders.d.ts +1 -1
  29. package/types/GifUtils/Utils.d.ts +1 -1
  30. package/types/ImageDrawer.d.ts +5 -4
  31. package/umd/GifUtils/Enums/DisposalMethod.js +12 -0
  32. package/umd/GifUtils/Types/GIFDataHeaders.js +11 -0
  33. package/umd/GifUtils/Utils.js +21 -43
  34. package/umd/ImageDrawer.js +44 -64
  35. package/umd/ImagePreloader.js +1 -1
  36. package/umd/Utils.js +1 -1
  37. package/umd/index.js +7 -30
  38. package/21.min.js +0 -2
  39. package/21.min.js.LICENSE.txt +0 -1
  40. package/618.min.js +0 -2
  41. package/618.min.js.LICENSE.txt +0 -1
  42. package/623.min.js +0 -2
  43. package/623.min.js.LICENSE.txt +0 -1
  44. package/dist_browser_GifUtils_Utils_js.js +0 -50
  45. package/dist_browser_ImageDrawer_js.js +0 -30
  46. package/dist_browser_ImagePreloader_js.js +0 -40
package/cjs/index.js CHANGED
@@ -1,31 +1,11 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
3
  exports.loadImageShape = void 0;
27
4
  const Utils_js_1 = require("./Utils.js");
5
+ const ImageDrawer_js_1 = require("./ImageDrawer.js");
6
+ const ImagePreloader_js_1 = require("./ImagePreloader.js");
28
7
  const engine_1 = require("@tsparticles/engine");
8
+ const Utils_js_2 = require("./GifUtils/Utils.js");
29
9
  const extLength = 3;
30
10
  function addLoadImageToEngine(engine) {
31
11
  if (engine.loadImage) {
@@ -55,8 +35,7 @@ function addLoadImageToEngine(engine) {
55
35
  engine.images.push(image);
56
36
  let imageFunc;
57
37
  if (data.gif) {
58
- const { loadGifImage } = await Promise.resolve().then(() => __importStar(require("./GifUtils/Utils.js")));
59
- imageFunc = loadGifImage;
38
+ imageFunc = Utils_js_2.loadGifImage;
60
39
  }
61
40
  else {
62
41
  imageFunc = data.replaceColor ? Utils_js_1.downloadSvgImage : Utils_js_1.loadImage;
@@ -70,9 +49,8 @@ function addLoadImageToEngine(engine) {
70
49
  }
71
50
  async function loadImageShape(engine, refresh = true) {
72
51
  addLoadImageToEngine(engine);
73
- const { ImagePreloaderPlugin } = await Promise.resolve().then(() => __importStar(require("./ImagePreloader.js"))), { ImageDrawer } = await Promise.resolve().then(() => __importStar(require("./ImageDrawer.js")));
74
- const preloader = new ImagePreloaderPlugin(engine);
52
+ const preloader = new ImagePreloader_js_1.ImagePreloaderPlugin(engine);
75
53
  await engine.addPlugin(preloader, refresh);
76
- await engine.addShape(["image", "images"], new ImageDrawer(engine), refresh);
54
+ await engine.addShape(new ImageDrawer_js_1.ImageDrawer(engine), refresh);
77
55
  }
78
56
  exports.loadImageShape = loadImageShape;
@@ -1 +1,11 @@
1
- export {};
1
+ export var DisposalMethod;
2
+ (function (DisposalMethod) {
3
+ DisposalMethod[DisposalMethod["Replace"] = 0] = "Replace";
4
+ DisposalMethod[DisposalMethod["Combine"] = 1] = "Combine";
5
+ DisposalMethod[DisposalMethod["RestoreBackground"] = 2] = "RestoreBackground";
6
+ DisposalMethod[DisposalMethod["RestorePrevious"] = 3] = "RestorePrevious";
7
+ DisposalMethod[DisposalMethod["UndefinedA"] = 4] = "UndefinedA";
8
+ DisposalMethod[DisposalMethod["UndefinedB"] = 5] = "UndefinedB";
9
+ DisposalMethod[DisposalMethod["UndefinedC"] = 6] = "UndefinedC";
10
+ DisposalMethod[DisposalMethod["UndefinedD"] = 7] = "UndefinedD";
11
+ })(DisposalMethod || (DisposalMethod = {}));
@@ -1 +1,10 @@
1
- export {};
1
+ export var GIFDataHeaders;
2
+ (function (GIFDataHeaders) {
3
+ GIFDataHeaders[GIFDataHeaders["Extension"] = 33] = "Extension";
4
+ GIFDataHeaders[GIFDataHeaders["ApplicationExtension"] = 255] = "ApplicationExtension";
5
+ GIFDataHeaders[GIFDataHeaders["GraphicsControlExtension"] = 249] = "GraphicsControlExtension";
6
+ GIFDataHeaders[GIFDataHeaders["PlainTextExtension"] = 1] = "PlainTextExtension";
7
+ GIFDataHeaders[GIFDataHeaders["CommentExtension"] = 254] = "CommentExtension";
8
+ GIFDataHeaders[GIFDataHeaders["Image"] = 44] = "Image";
9
+ GIFDataHeaders[GIFDataHeaders["EndOfFile"] = 59] = "EndOfFile";
10
+ })(GIFDataHeaders || (GIFDataHeaders = {}));
@@ -1,5 +1,8 @@
1
+ import { loadImage } from "../Utils.js";
1
2
  import { InterlaceOffsets, InterlaceSteps } from "./Constants.js";
2
3
  import { ByteStream } from "./ByteStream.js";
4
+ import { DisposalMethod } from "./Enums/DisposalMethod.js";
5
+ import { GIFDataHeaders } from "./Types/GIFDataHeaders.js";
3
6
  const origin = {
4
7
  x: 0,
5
8
  y: 0,
@@ -18,7 +21,7 @@ function parseColorTable(byteStream, count) {
18
21
  }
19
22
  function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex) {
20
23
  switch (byteStream.nextByte()) {
21
- case 249: {
24
+ case GIFDataHeaders.GraphicsControlExtension: {
22
25
  const frame = gif.frames[getFrameIndex(false)];
23
26
  byteStream.pos++;
24
27
  const packedByte = byteStream.nextByte();
@@ -34,7 +37,7 @@ function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyInde
34
37
  byteStream.pos++;
35
38
  break;
36
39
  }
37
- case 255: {
40
+ case GIFDataHeaders.ApplicationExtension: {
38
41
  byteStream.pos++;
39
42
  const applicationExtension = {
40
43
  identifier: byteStream.getString(8),
@@ -44,11 +47,11 @@ function parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyInde
44
47
  gif.applicationExtensions.push(applicationExtension);
45
48
  break;
46
49
  }
47
- case 254: {
50
+ case GIFDataHeaders.CommentExtension: {
48
51
  gif.comments.push([getFrameIndex(false), byteStream.readSubBlocks()]);
49
52
  break;
50
53
  }
51
- case 1: {
54
+ case GIFDataHeaders.PlainTextExtension: {
52
55
  if (gif.globalColorTable.length === 0) {
53
56
  throw new EvalError("plain text extension without global color table");
54
57
  }
@@ -201,12 +204,12 @@ async function parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTran
201
204
  }
202
205
  async function parseBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback) {
203
206
  switch (byteStream.nextByte()) {
204
- case 59:
207
+ case GIFDataHeaders.EndOfFile:
205
208
  return true;
206
- case 44:
209
+ case GIFDataHeaders.Image:
207
210
  await parseImageBlock(byteStream, gif, avgAlpha, getFrameIndex, getTransparencyIndex, progressCallback);
208
211
  break;
209
- case 33:
212
+ case GIFDataHeaders.Extension:
210
213
  parseExtensionBlock(byteStream, gif, getFrameIndex, getTransparencyIndex);
211
214
  break;
212
215
  default:
@@ -301,7 +304,7 @@ export async function decodeGIF(gifURL, progressCallback, avgAlpha) {
301
304
  top: 0,
302
305
  width: 0,
303
306
  height: 0,
304
- disposalMethod: 0,
307
+ disposalMethod: DisposalMethod.Replace,
305
308
  image: new ImageData(1, 1, { colorSpace: "srgb" }),
306
309
  plainTextData: null,
307
310
  userInputDelayFlag: false,
@@ -358,20 +361,20 @@ export function drawGif(data) {
358
361
  }
359
362
  context.scale(radius / image.gifData.width, radius / image.gifData.height);
360
363
  switch (frame.disposalMethod) {
361
- case 4:
362
- case 5:
363
- case 6:
364
- case 7:
365
- case 0:
364
+ case DisposalMethod.UndefinedA:
365
+ case DisposalMethod.UndefinedB:
366
+ case DisposalMethod.UndefinedC:
367
+ case DisposalMethod.UndefinedD:
368
+ case DisposalMethod.Replace:
366
369
  offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
367
370
  context.drawImage(offscreenCanvas, pos.x, pos.y);
368
371
  offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
369
372
  break;
370
- case 1:
373
+ case DisposalMethod.Combine:
371
374
  offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
372
375
  context.drawImage(offscreenCanvas, pos.x, pos.y);
373
376
  break;
374
- case 2:
377
+ case DisposalMethod.RestoreBackground:
375
378
  offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
376
379
  context.drawImage(offscreenCanvas, pos.x, pos.y);
377
380
  offscreenContext.clearRect(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
@@ -382,7 +385,7 @@ export function drawGif(data) {
382
385
  offscreenContext.putImageData(image.gifData.backgroundImage, pos.x, pos.y);
383
386
  }
384
387
  break;
385
- case 3:
388
+ case DisposalMethod.RestorePrevious:
386
389
  {
387
390
  const previousImageData = offscreenContext.getImageData(origin.x, origin.y, offscreenCanvas.width, offscreenCanvas.height);
388
391
  offscreenContext.drawImage(frame.bitmap, frame.left, frame.top);
@@ -408,7 +411,6 @@ export function drawGif(data) {
408
411
  }
409
412
  export async function loadGifImage(image) {
410
413
  if (image.type !== "gif") {
411
- const { loadImage } = await import("../Utils.js");
412
414
  await loadImage(image);
413
415
  return;
414
416
  }
@@ -1,7 +1,10 @@
1
1
  import { errorPrefix } from "@tsparticles/engine";
2
+ import { replaceImageColor } from "./Utils.js";
3
+ import { drawGif } from "./GifUtils/Utils.js";
2
4
  const double = 2, defaultAlpha = 1, sides = 12, defaultRatio = 1;
3
5
  export class ImageDrawer {
4
6
  constructor(engine) {
7
+ this.validTypes = ["image", "images"];
5
8
  this.loadImageShape = async (imageShape) => {
6
9
  if (!this._engine.loadImage) {
7
10
  throw new Error(`${errorPrefix} image shape not initialized`);
@@ -21,14 +24,13 @@ export class ImageDrawer {
21
24
  }
22
25
  this._engine.images.push(image);
23
26
  }
24
- async draw(data) {
27
+ draw(data) {
25
28
  const { context, radius, particle, opacity } = data, image = particle.image, element = image?.element;
26
29
  if (!image) {
27
30
  return;
28
31
  }
29
32
  context.globalAlpha = opacity;
30
33
  if (image.gif && image.gifData) {
31
- const { drawGif } = await import("./GifUtils/Utils.js");
32
34
  drawGif(data);
33
35
  }
34
36
  else if (element) {
@@ -52,7 +54,7 @@ export class ImageDrawer {
52
54
  await this._engine.loadImage(imageData);
53
55
  }
54
56
  }
55
- async loadShape(particle) {
57
+ loadShape(particle) {
56
58
  if (particle.shape !== "image" && particle.shape !== "images") {
57
59
  return;
58
60
  }
@@ -65,11 +67,12 @@ export class ImageDrawer {
65
67
  }
66
68
  const image = this._engine.images.find((t) => t.name === imageData.name || t.source === imageData.src);
67
69
  if (!image) {
68
- await this.loadImageShape(imageData);
69
- await this.loadShape(particle);
70
+ void this.loadImageShape(imageData).then(() => {
71
+ this.loadShape(particle);
72
+ });
70
73
  }
71
74
  }
72
- async particleInit(container, particle) {
75
+ particleInit(container, particle) {
73
76
  if (particle.shape !== "image" && particle.shape !== "images") {
74
77
  return;
75
78
  }
@@ -87,41 +90,42 @@ export class ImageDrawer {
87
90
  const replaceColor = imageData.replaceColor ?? image.replaceColor;
88
91
  if (image.loading) {
89
92
  setTimeout(() => {
90
- void this.particleInit(container, particle);
93
+ this.particleInit(container, particle);
91
94
  });
92
95
  return;
93
96
  }
94
- let imageRes;
95
- if (image.svgData && color) {
96
- const { replaceImageColor } = await import("./Utils.js");
97
- imageRes = await replaceImageColor(image, imageData, color, particle);
98
- }
99
- else {
100
- imageRes = {
101
- color,
102
- data: image,
103
- element: image.element,
104
- gif: image.gif,
105
- gifData: image.gifData,
106
- gifLoopCount: image.gifLoopCount,
107
- loaded: true,
108
- ratio: imageData.width && imageData.height
109
- ? imageData.width / imageData.height
110
- : image.ratio ?? defaultRatio,
111
- replaceColor: replaceColor,
112
- source: imageData.src,
97
+ void (async () => {
98
+ let imageRes;
99
+ if (image.svgData && color) {
100
+ imageRes = await replaceImageColor(image, imageData, color, particle);
101
+ }
102
+ else {
103
+ imageRes = {
104
+ color,
105
+ data: image,
106
+ element: image.element,
107
+ gif: image.gif,
108
+ gifData: image.gifData,
109
+ gifLoopCount: image.gifLoopCount,
110
+ loaded: true,
111
+ ratio: imageData.width && imageData.height
112
+ ? imageData.width / imageData.height
113
+ : image.ratio ?? defaultRatio,
114
+ replaceColor: replaceColor,
115
+ source: imageData.src,
116
+ };
117
+ }
118
+ if (!imageRes.ratio) {
119
+ imageRes.ratio = 1;
120
+ }
121
+ const fill = imageData.fill ?? particle.shapeFill, close = imageData.close ?? particle.shapeClose, imageShape = {
122
+ image: imageRes,
123
+ fill,
124
+ close,
113
125
  };
114
- }
115
- if (!imageRes.ratio) {
116
- imageRes.ratio = 1;
117
- }
118
- const fill = imageData.fill ?? particle.shapeFill, close = imageData.close ?? particle.shapeClose, imageShape = {
119
- image: imageRes,
120
- fill,
121
- close,
122
- };
123
- particle.image = imageShape.image;
124
- particle.shapeFill = imageShape.fill;
125
- particle.shapeClose = imageShape.close;
126
+ particle.image = imageShape.image;
127
+ particle.shapeFill = imageShape.fill;
128
+ particle.shapeClose = imageShape.close;
129
+ })();
126
130
  }
127
131
  }
@@ -17,7 +17,7 @@ export class ImagePreloaderPlugin {
17
17
  }
18
18
  const preloadOptions = options.preload;
19
19
  for (const item of source.preload) {
20
- const existing = preloadOptions.find((t) => t.name === item.name || t.src === item.src);
20
+ const existing = preloadOptions.find(t => t.name === item.name || t.src === item.src);
21
21
  if (existing) {
22
22
  existing.load(item);
23
23
  }
package/esm/Utils.js CHANGED
@@ -61,7 +61,7 @@ export function replaceImageColor(image, imageData, color, particle) {
61
61
  replaceColor: imageData.replaceColor,
62
62
  source: imageData.src,
63
63
  };
64
- return new Promise((resolve) => {
64
+ return new Promise(resolve => {
65
65
  const svg = new Blob([svgColoredData], { type: "image/svg+xml" }), domUrl = URL || window.URL || window.webkitURL || window, url = domUrl.createObjectURL(svg), img = new Image();
66
66
  img.addEventListener("load", () => {
67
67
  imageRes.loaded = true;
package/esm/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  import { downloadSvgImage, loadImage } from "./Utils.js";
2
+ import { ImageDrawer } from "./ImageDrawer.js";
3
+ import { ImagePreloaderPlugin } from "./ImagePreloader.js";
2
4
  import { errorPrefix } from "@tsparticles/engine";
5
+ import { loadGifImage } from "./GifUtils/Utils.js";
3
6
  const extLength = 3;
4
7
  function addLoadImageToEngine(engine) {
5
8
  if (engine.loadImage) {
@@ -29,7 +32,6 @@ function addLoadImageToEngine(engine) {
29
32
  engine.images.push(image);
30
33
  let imageFunc;
31
34
  if (data.gif) {
32
- const { loadGifImage } = await import("./GifUtils/Utils.js");
33
35
  imageFunc = loadGifImage;
34
36
  }
35
37
  else {
@@ -44,8 +46,7 @@ function addLoadImageToEngine(engine) {
44
46
  }
45
47
  export async function loadImageShape(engine, refresh = true) {
46
48
  addLoadImageToEngine(engine);
47
- const { ImagePreloaderPlugin } = await import("./ImagePreloader.js"), { ImageDrawer } = await import("./ImageDrawer.js");
48
49
  const preloader = new ImagePreloaderPlugin(engine);
49
50
  await engine.addPlugin(preloader, refresh);
50
- await engine.addShape(["image", "images"], new ImageDrawer(engine), refresh);
51
+ await engine.addShape(new ImageDrawer(engine), refresh);
51
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/shape-image",
3
- "version": "3.2.2",
3
+ "version": "3.4.0",
4
4
  "description": "tsParticles image shape",
5
5
  "homepage": "https://particles.js.org",
6
6
  "repository": {
@@ -59,7 +59,7 @@
59
59
  "./package.json": "./package.json"
60
60
  },
61
61
  "dependencies": {
62
- "@tsparticles/engine": "^3.2.2"
62
+ "@tsparticles/engine": "^3.4.0"
63
63
  },
64
64
  "publishConfig": {
65
65
  "access": "public"
package/report.html CHANGED
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8"/>
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1"/>
6
- <title>@tsparticles/shape-image [20 Feb 2024 at 01:38]</title>
6
+ <title>@tsparticles/shape-image [13 May 2024 at 00:12]</title>
7
7
  <link rel="shortcut icon" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAMAAACdt4HsAAABrVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O1foceMD///+J0/qK1Pr7/v8Xdr/9///W8P4UdL7L7P0Scr2r4Pyj3vwad8D5/f/2/f+55f3E6f34+/2H0/ojfMKpzOd0rNgQcb3F3O/j9f7c8v6g3Pz0/P/w+v/q+P7n9v6T1/uQ1vuE0vqLut/y+v+Z2fvt+f+15Pzv9fuc2/vR7v2V2Pvd6/bg9P7I6/285/2y4/yp3/zp8vk8i8kqgMT7/P31+fyv4vxGkcz6/P6/6P3j7vfS5PNnpNUxhcbO7f7F6v3O4vHK3/DA2u631Ouy0eqXweKJud5wqthfoNMMbLvY8f73+v2dxeR8sNtTmdDx9/zX6PSjyeaCtd1YnNGX2PuQveCGt95Nls42h8dLlM3F4vBtAAAAM3RSTlMAAyOx0/sKBvik8opWGBMOAe3l1snDm2E9LSb06eHcu5JpHbarfHZCN9CBb08zzkdNS0kYaptYAAAFV0lEQVRYw92X51/aYBDHHS2O2qqttVbrqNq9m+TJIAYIShBkWwqIiCgoWvfeq7Z2/s29hyQNyUcR7LveGwVyXy6XH8/9rqxglLfUPLxVduUor3h0rfp2TYvpivk37929TkG037hffoX0+peVtZQc1589rigVUdXS/ABSAyEmGIO/1XfvldSK8vs3OqB6u3m0nxmIrvgB0dj7rr7Y9IbuF68hnfFaiHA/sxqm0wciIG43P60qKv9WXWc1RXGh/mFESFABTSBi0sNAKzqet17eCtOb3kZIDwxEEU0oAIJGYxNBDhBND29e0rtXXbcpuPmED9IhEAAQ/AXEaF8EPmnrrKsv0LvWR3fg5sWDNAFZOgAgaKvZDogHNU9MFwnnYROkc56RD5CjAbQX9Ow4g7upCsvYu55aSI/Nj0H1akgKQEUM94dwK65hYRmFU9MIcH/fqJYOZYcnuJSU/waKDgTOEVaVKhwrTRP5XzgSpAITYzom7UvkhFX5VutmxeNnWDjjswTKTyfgluNDGbUpWissXhF3s7mlSml+czWkg3D0l1nNjGNjz3myOQOa1KM/jOS6ebdbAVTCi4gljHSFrviza7tOgRWcS0MOUX9zdNgag5w7rRqA44Lzw0hr1WqES36dFliSJFlh2rXIae3FFcDDgKdxrUIDePr8jGcSClV1u7A9xeN0ModY/pHMxmR1EzRh8TJiwqsHmKW0l4FCEZI+jHio+JdPPE9qwQtTRxku2D8sIeRL2LnxWSllANCQGOIiqVHAz2ye2JR0DcH+HoxDkaADLjgxjKQ+AwCX/g0+DNgdG0ukYCONAe+dbc2IAc6fwt1ARoDSezNHxV2Cmzwv3O6lDMV55edBGwGK9n1+x2F8EDfAGCxug8MhpsMEcTEAWf3rx2vZhe/LAmtIn/6apE6PN0ULKgywD9mmdxbmFl3OvD5AS5fW5zLbv/YHmcsBTjf/afDz3MaZTVCfAP9z6/Bw6ycv8EUBWJIn9zYcoAWWlW9+OzO3vkTy8H+RANLmdrpOuYWdZYEXpo+TlCJrW5EARb7fF+bWdqf3hhyZI1nWJQHgznErZhbjoEsWqi8dQNoE294aldzFurwSABL2XXMf9+H1VQGke9exw5P/AnA5Pv5ngMul7LOvO922iwACu8WkCwLCafvM4CeWPxfA8lNHcWZSoi8EwMAIciKX2Z4SWCMAa3snCZ/G4EA8D6CMLNFsGQhkkz/gQNEBbPCbWsxGUpYVu3z8IyNAknwJkfPMEhLyrdi5RTyUVACkw4GSFRNWJNEW+fgPGwHD8/JxnRuLabN4CGNRkAE23na2+VmEAUmrYymSGjMAYqH84YUIyzgzs3XC7gNgH36Vcc4zKY9o9fgPBXUAiHHwVboBHGLiX6Zcjp1f2wu4tvzZKo0ecPnDtQYDQvJXaBeNzce45Fp28ZQLrEZVuFqgBwOalArKXnW1UzlnSusQKJqKYNuz4tOnI6sZG4zanpemv+7ySU2jbA9h6uhcgpfy6G2PahirDZ6zvq6zDduMVFTKvzw8wgyEdelwY9in3XkEPs3osJuwRQ4qTkfzifndg9Gfc4pdsu82+tTnHZTBa2EAMrqr2t43pguc8tNm7JQVQ2S0ukj2d22dhXYP0/veWtwKrCkNoNimAN5+Xr/oLrxswKbVJjteWrX7eR63o4j9q0GxnaBdWgGA5VStpanIjQmEhV0/nVt5VOFUvix6awJhPcAaTEShgrG+iGyvb5a0Ndb1YGHFPEwoqAinoaykaID1o1pdPNu7XsnCKQ3R+hwWIIhGvORcJUBYXe3Xa3vq/mF/N9V13ugufMkfXn+KHsRD0B8AAAAASUVORK5CYII=" type="image/x-icon" />
8
8
 
9
9
  <script>