|   | 
| import LRU from '../../core/LRU'; | 
| import { platformApi } from '../../core/platform'; | 
| import { ImageLike } from '../../core/types'; | 
|   | 
| const globalImageCache = new LRU<CachedImageObj>(50); | 
|   | 
| type PendingWrap = { | 
|     hostEl: {dirty: () => void} | 
|     cb: (image: ImageLike, payload: any) => void | 
|     cbPayload: any | 
| } | 
|   | 
| type CachedImageObj = { | 
|     image: ImageLike | 
|     pending: PendingWrap[] | 
| } | 
|   | 
| export function findExistImage(newImageOrSrc: string | ImageLike): ImageLike { | 
|     if (typeof newImageOrSrc === 'string') { | 
|         const cachedImgObj = globalImageCache.get(newImageOrSrc); | 
|         return cachedImgObj && cachedImgObj.image; | 
|     } | 
|     else { | 
|         return newImageOrSrc; | 
|     } | 
| } | 
|   | 
| /** | 
|  * Caution: User should cache loaded images, but not just count on LRU. | 
|  * Consider if required images more than LRU size, will dead loop occur? | 
|  * | 
|  * @param newImageOrSrc | 
|  * @param image Existent image. | 
|  * @param hostEl For calling `dirty`. | 
|  * @param onload params: (image, cbPayload) | 
|  * @param cbPayload Payload on cb calling. | 
|  * @return image | 
|  */ | 
| export function createOrUpdateImage<T>( | 
|     newImageOrSrc: string | ImageLike, | 
|     image: ImageLike, | 
|     hostEl: { dirty: () => void }, | 
|     onload?: (image: ImageLike, payload: T) => void, | 
|     cbPayload?: T | 
| ) { | 
|     if (!newImageOrSrc) { | 
|         return image; | 
|     } | 
|     else if (typeof newImageOrSrc === 'string') { | 
|   | 
|         // Image should not be loaded repeatly. | 
|         if ((image && (image as any).__zrImageSrc === newImageOrSrc) || !hostEl) { | 
|             return image; | 
|         } | 
|   | 
|         // Only when there is no existent image or existent image src | 
|         // is different, this method is responsible for load. | 
|         const cachedImgObj = globalImageCache.get(newImageOrSrc); | 
|   | 
|         const pendingWrap = {hostEl: hostEl, cb: onload, cbPayload: cbPayload}; | 
|   | 
|         if (cachedImgObj) { | 
|             image = cachedImgObj.image; | 
|             !isImageReady(image) && cachedImgObj.pending.push(pendingWrap); | 
|         } | 
|         else { | 
|             image = platformApi.loadImage( | 
|                 newImageOrSrc, imageOnLoad, imageOnLoad | 
|             ); | 
|             (image as any).__zrImageSrc = newImageOrSrc; | 
|   | 
|             globalImageCache.put( | 
|                 newImageOrSrc, | 
|                 (image as any).__cachedImgObj = { | 
|                     image: image, | 
|                     pending: [pendingWrap] | 
|                 } | 
|             ); | 
|         } | 
|   | 
|         return image; | 
|     } | 
|     // newImageOrSrc is an HTMLImageElement or HTMLCanvasElement or Canvas | 
|     else { | 
|         return newImageOrSrc; | 
|     } | 
| } | 
|   | 
| function imageOnLoad(this: any) { | 
|     const cachedImgObj = this.__cachedImgObj; | 
|     this.onload = this.onerror = this.__cachedImgObj = null; | 
|   | 
|     for (let i = 0; i < cachedImgObj.pending.length; i++) { | 
|         const pendingWrap = cachedImgObj.pending[i]; | 
|         const cb = pendingWrap.cb; | 
|         cb && cb(this, pendingWrap.cbPayload); | 
|         pendingWrap.hostEl.dirty(); | 
|     } | 
|     cachedImgObj.pending.length = 0; | 
| } | 
|   | 
| export function isImageReady(image: ImageLike) { | 
|     return image && image.width && image.height; | 
| } |