| 
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; 
 | 
} 
 |