680 lines
24 KiB
JavaScript
680 lines
24 KiB
JavaScript
/*
|
||
* (c) Copyright Ascensio System SIA 2010-2024
|
||
*
|
||
* This program is a free software product. You can redistribute it and/or
|
||
* modify it under the terms of the GNU Affero General Public License (AGPL)
|
||
* version 3 as published by the Free Software Foundation. In accordance with
|
||
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
|
||
* that Ascensio System SIA expressly excludes the warranty of non-infringement
|
||
* of any third-party rights.
|
||
*
|
||
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
|
||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
|
||
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
|
||
*
|
||
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
|
||
* street, Riga, Latvia, EU, LV-1050.
|
||
*
|
||
* The interactive user interfaces in modified source and object code versions
|
||
* of the Program must display Appropriate Legal Notices, as required under
|
||
* Section 5 of the GNU AGPL version 3.
|
||
*
|
||
* Pursuant to Section 7(b) of the License you must retain the original Product
|
||
* logo when distributing the program. Pursuant to Section 7(e) we decline to
|
||
* grant you any rights under trademark law for use of our trademarks.
|
||
*
|
||
* All the Product's GUI elements, including illustrations and icon sets, as
|
||
* well as technical writing content are licensed under the terms of the
|
||
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
|
||
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
|
||
*
|
||
*/
|
||
|
||
"use strict";
|
||
|
||
(function(window, document){
|
||
// Import
|
||
var g_fontApplication = AscFonts.g_fontApplication;
|
||
var ImageLoadStatus = AscFonts.ImageLoadStatus;
|
||
var CImage = AscFonts.CImage;
|
||
|
||
function CGlobalFontLoader()
|
||
{
|
||
// сначала хотел писать "вытеснение" из этого мапа.
|
||
// но тогда нужно хранить base64 строки. Это не круто. По памяти - даже
|
||
// выигрыш будет. Не особо то шрифты жмутся lzw или deflate
|
||
// поэтому лучше из памяти будем удалять base64 строки
|
||
this.fonts_streams = [];
|
||
|
||
// теперь вся информация о всех возможных шрифтах. Они во всех редакторах должны быть одни и те же
|
||
this.fontFilesPath = "../../../../fonts/";
|
||
this.fontFiles = AscFonts.g_font_files;
|
||
this.fontInfos = AscFonts.g_font_infos;
|
||
this.map_font_index = AscFonts.g_map_font_index;
|
||
|
||
// динамическая подгрузка шрифтов
|
||
this.ThemeLoader = null;
|
||
this.Api = null;
|
||
this.fonts_loading = [];
|
||
this.bIsLoadDocumentFirst = false;
|
||
|
||
// информация для загрузки по одному шрифту
|
||
this.currentInfoLoaded = null;
|
||
this.loadFontCallBack = null;
|
||
this.loadFontCallBackArgs = null;
|
||
|
||
// при переоткрытиях файла - заменить на LoadDocumentFonts2
|
||
this.IsLoadDocumentFonts2 = false;
|
||
|
||
this.check_loaded_timer_id = -1;
|
||
this.endLoadingCallback = null;
|
||
|
||
// Счетчик загрузки шрифтов через метод LoadFonts
|
||
this.loadFontsCounter = 0;
|
||
|
||
this.perfStart = 0;
|
||
|
||
this.put_Api = function(api)
|
||
{
|
||
this.Api = api;
|
||
};
|
||
|
||
// добавляем шрифт в список для загрузки
|
||
this.AddLoadFonts = function(name, need_styles)
|
||
{
|
||
var fontinfo = g_fontApplication.GetFontInfo(name);
|
||
this.fonts_loading[this.fonts_loading.length] = fontinfo;
|
||
this.fonts_loading[this.fonts_loading.length - 1].NeedStyles = (need_styles === undefined) ? 0x0F : need_styles;
|
||
return fontinfo;
|
||
};
|
||
this.AddLoadFontsNotPick = function(info, need_styles)
|
||
{
|
||
this.fonts_loading[this.fonts_loading.length] = info;
|
||
this.fonts_loading[this.fonts_loading.length - 1].NeedStyles = (need_styles === undefined) ? 0x0F : need_styles;
|
||
};
|
||
|
||
// проверить все fontinfo из fonts_loading на нужность загрузки, и вернуть есть ли хоть один заново запущенный
|
||
this.CheckFontsNeedLoadingLoad = function()
|
||
{
|
||
let fonts = this.fonts_loading;
|
||
let isNeed = false;
|
||
for (let i = 0, len = fonts.length; i < len; i++)
|
||
{
|
||
if (true === fonts[i].CheckFontLoadStyles(this))
|
||
isNeed = true;
|
||
}
|
||
return isNeed;
|
||
};
|
||
|
||
// нужно ли грузить хоть один из списка (без запуска загрузки)
|
||
this.CheckFontsNeedLoading = function(fonts)
|
||
{
|
||
for (let i in fonts)
|
||
{
|
||
let info = g_fontApplication.GetFontInfo(fonts[i].name);
|
||
if (true === info.CheckFontLoadStylesNoLoad(this))
|
||
return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
this.isWorking = function()
|
||
{
|
||
return (this.check_loaded_timer_id !== -1) ? true : false;
|
||
};
|
||
|
||
this.LoadDocumentFonts = function(fonts)
|
||
{
|
||
if (this.IsLoadDocumentFonts2)
|
||
return this.LoadDocumentFonts2(fonts);
|
||
|
||
let gui_fonts = [];
|
||
let gui_count = 0;
|
||
for (let i = 0; i < this.fontInfos.length; i++)
|
||
{
|
||
let info = this.fontInfos[i];
|
||
if (info.Name !== "ASCW3")
|
||
gui_fonts[gui_count++] = new AscFonts.CFont(info.Name, "", info.Thumbnail);
|
||
}
|
||
|
||
// сначала заполняем массив this.fonts_loading объекстами fontinfo
|
||
for (let i in fonts)
|
||
{
|
||
this.AddLoadFonts(fonts[i].name, fonts[i].NeedStyles);
|
||
}
|
||
|
||
this.Api.sync_InitEditorFonts(gui_fonts);
|
||
|
||
// но только если редактор!!!
|
||
if (this.Api.IsNeedDefaultFonts())
|
||
{
|
||
// теперь добавим шрифты, без которых редактор как без рук (спецсимволы + дефолтовые стили документа)
|
||
this.AddLoadFonts("Arial", 0x0F);
|
||
this.AddLoadFonts("Symbol", 0x0F);
|
||
this.AddLoadFonts("Wingdings", 0x0F);
|
||
this.AddLoadFonts("Courier New", 0x0F);
|
||
this.AddLoadFonts("Times New Roman", 0x0F);
|
||
}
|
||
|
||
this.Api.asyncFontsDocumentStartLoaded();
|
||
|
||
this.bIsLoadDocumentFirst = true;
|
||
|
||
this.CheckFontsNeedLoadingLoad();
|
||
this._LoadFonts();
|
||
};
|
||
|
||
this.LoadDocumentFonts2 = function(fonts, blockType, callback)
|
||
{
|
||
if (this.isWorking())
|
||
{
|
||
// такого быть не должно
|
||
return;
|
||
}
|
||
|
||
this.endLoadingCallback = (undefined !== callback) ? callback : null;
|
||
this.BlockOperationType = blockType;
|
||
|
||
// сначала заполняем массив this.fonts_loading объекстами fontinfo
|
||
for (var i in fonts)
|
||
this.AddLoadFonts(fonts[i].name, 0x0F);
|
||
|
||
if (null == this.ThemeLoader)
|
||
this.Api.asyncFontsDocumentStartLoaded(this.BlockOperationType);
|
||
else
|
||
this.ThemeLoader.asyncFontsStartLoaded();
|
||
|
||
this.CheckFontsNeedLoadingLoad();
|
||
this._LoadFonts();
|
||
};
|
||
|
||
this._LoadFonts = function()
|
||
{
|
||
if (this.bIsLoadDocumentFirst === true && 0 === this.perfStart && this.fonts_loading.length > 0)
|
||
this.perfStart = performance.now();
|
||
|
||
if (0 === this.fonts_loading.length)
|
||
{
|
||
if (this.perfStart > 0)
|
||
{
|
||
let perfEnd = performance.now();
|
||
AscCommon.sendClientLog("debug", AscCommon.getClientInfoString("onLoadFonts", perfEnd - this.perfStart), this.Api);
|
||
this.perfStart = 0;
|
||
}
|
||
|
||
if (null != this.endLoadingCallback)
|
||
{
|
||
this.endLoadingCallback.call(this.Api);
|
||
this.endLoadingCallback = null;
|
||
}
|
||
else if (null == this.ThemeLoader)
|
||
this.Api.asyncFontsDocumentEndLoaded(this.BlockOperationType);
|
||
else
|
||
this.ThemeLoader.asyncFontsEndLoaded();
|
||
|
||
this.BlockOperationType = undefined;
|
||
this.bIsLoadDocumentFirst = false;
|
||
return;
|
||
}
|
||
|
||
if (this.fonts_loading[0].CheckFontLoadStyles(this))
|
||
{
|
||
let _t = this;
|
||
this.check_loaded_timer_id = setTimeout(function(){
|
||
_t.check_loaded_list();
|
||
}, 50);
|
||
}
|
||
else
|
||
{
|
||
if (this.bIsLoadDocumentFirst === true)
|
||
{
|
||
this.Api.OpenDocumentProgress.CurrentFont++;
|
||
this.Api.SendOpenProgress();
|
||
}
|
||
|
||
this.fonts_loading.shift();
|
||
this._LoadFonts();
|
||
}
|
||
};
|
||
|
||
this.check_loaded_list = function()
|
||
{
|
||
this.check_loaded_timer_id = -1;
|
||
if (0 === this.fonts_loading.length)
|
||
{
|
||
// значит асинхронно удалилось
|
||
this._LoadFonts();
|
||
return;
|
||
}
|
||
|
||
let current = this.fonts_loading[0];
|
||
let isNeed = current.CheckFontLoadStyles(this);
|
||
if (true === isNeed)
|
||
{
|
||
let _t = this;
|
||
this.check_loaded_timer_id = setTimeout(function(){
|
||
_t.check_loaded_list();
|
||
}, 50);
|
||
}
|
||
else
|
||
{
|
||
if (this.bIsLoadDocumentFirst === true)
|
||
{
|
||
this.Api.OpenDocumentProgress.CurrentFont++;
|
||
this.Api.SendOpenProgress();
|
||
}
|
||
|
||
this.fonts_loading.shift();
|
||
this._LoadFonts();
|
||
}
|
||
};
|
||
|
||
// одиночная загрузка шрифта
|
||
this.LoadFont = function(fontinfo, loadFontCallBack, loadFontCallBackArgs)
|
||
{
|
||
this.currentInfoLoaded = fontinfo;
|
||
this.currentInfoLoaded.NeedStyles = 15; // все стили
|
||
|
||
let isNeed = this.currentInfoLoaded.CheckFontLoadStyles(this);
|
||
|
||
if ( undefined === loadFontCallBack )
|
||
{
|
||
this.loadFontCallBack = this.Api.asyncFontEndLoaded;
|
||
this.loadFontCallBackArgs = this.currentInfoLoaded;
|
||
}
|
||
else
|
||
{
|
||
this.loadFontCallBack = loadFontCallBack;
|
||
this.loadFontCallBackArgs = loadFontCallBackArgs;
|
||
}
|
||
|
||
if (isNeed)
|
||
{
|
||
this.Api.asyncFontStartLoaded();
|
||
let _t = this;
|
||
setTimeout(function() {
|
||
_t.check_loaded();
|
||
}, 20);
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
this.currentInfoLoaded = null;
|
||
return false;
|
||
}
|
||
};
|
||
this.check_loaded = function()
|
||
{
|
||
if (!this.currentInfoLoaded)
|
||
return;
|
||
|
||
let isNeed = this.currentInfoLoaded.CheckFontLoadStyles(this);
|
||
if (isNeed)
|
||
{
|
||
let _t = this;
|
||
setTimeout(function() {
|
||
_t.check_loaded();
|
||
}, 50);
|
||
}
|
||
else
|
||
{
|
||
this.loadFontCallBack.call( this.Api, this.loadFontCallBackArgs );
|
||
this.currentInfoLoaded = null;
|
||
}
|
||
};
|
||
|
||
// используется только в тестовом примере (предзагрузка в кэш браузера)
|
||
this.LoadFontsFromServer = function(fonts)
|
||
{
|
||
let count = fonts.length;
|
||
for (let i = 0; i < count; i++)
|
||
{
|
||
let info = g_fontApplication.GetFontInfo(fonts[i]);
|
||
info && info.LoadFontsFromServer(this);
|
||
}
|
||
};
|
||
|
||
this.isFontLoadInProgress = function()
|
||
{
|
||
return (this.isWorking() || this.loadFontsCounter > 0);
|
||
};
|
||
|
||
this.LoadFonts = function(fonts, callback)
|
||
{
|
||
++this.loadFontsCounter;
|
||
|
||
let fontMap = {}
|
||
|
||
if (fonts && Array.isArray(fonts))
|
||
{
|
||
for (let i = 0; i < fonts.length; ++i)
|
||
{
|
||
let name = fonts[i];
|
||
fontMap[name] = AscFonts.g_fontApplication.GetFontInfo(name);
|
||
fontMap[name].NeedStyles = 15;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
for (let name in fonts)
|
||
{
|
||
fontMap[name] = AscFonts.g_fontApplication.GetFontInfo(name);
|
||
fontMap[name].NeedStyles = 15;
|
||
}
|
||
}
|
||
|
||
|
||
let globalLoader = this;
|
||
|
||
let checkLoaded = function()
|
||
{
|
||
let needLoad = 0;
|
||
for (let name in fontMap)
|
||
{
|
||
if (!fontMap[name].CheckFontLoadStyles(globalLoader))
|
||
delete fontMap[name];
|
||
else
|
||
++needLoad;
|
||
}
|
||
|
||
if (needLoad)
|
||
return setTimeout(checkLoaded, 50);
|
||
|
||
if (callback)
|
||
callback();
|
||
|
||
--globalLoader.loadFontsCounter;
|
||
};
|
||
checkLoaded();
|
||
}
|
||
}
|
||
|
||
function CGlobalImageLoader()
|
||
{
|
||
this.map_image_index = {};
|
||
|
||
// loading
|
||
this.Api = null;
|
||
this.ThemeLoader = null;
|
||
|
||
this.bIsLoadDocumentFirst = false;
|
||
this.bIsAsyncLoadDocumentImages = false;
|
||
|
||
this.isBlockchainSupport = false;
|
||
var oThis = this;
|
||
|
||
if (window["AscDesktopEditor"] &&
|
||
window["AscDesktopEditor"]["IsLocalFile"] &&
|
||
window["AscDesktopEditor"]["isBlockchainSupport"])
|
||
{
|
||
this.isBlockchainSupport = (window["AscDesktopEditor"]["isBlockchainSupport"]() && !window["AscDesktopEditor"]["IsLocalFile"]());
|
||
|
||
if (this.isBlockchainSupport)
|
||
{
|
||
Image.prototype.preload_crypto = function(_url)
|
||
{
|
||
window["crypto_images_map"] = window["crypto_images_map"] || {};
|
||
if (!window["crypto_images_map"][_url])
|
||
window["crypto_images_map"][_url] = [];
|
||
window["crypto_images_map"][_url].push(this);
|
||
|
||
window["AscDesktopEditor"]["PreloadCryptoImage"](_url, AscCommon.g_oDocumentUrls.getLocal(_url));
|
||
|
||
oThis.Api.sync_StartAction(Asc.c_oAscAsyncActionType.BlockInteraction, Asc.c_oAscAsyncAction.LoadImage);
|
||
};
|
||
|
||
Image.prototype["onload_crypto"] = function(_src, _crypto_data)
|
||
{
|
||
if (_crypto_data && AscCommon.EncryptionWorker && AscCommon.EncryptionWorker.isCryptoImages())
|
||
{
|
||
AscCommon.EncryptionWorker.decryptImage(_src, this, _crypto_data);
|
||
return;
|
||
}
|
||
this.crossOrigin = "";
|
||
this.src = _src;
|
||
oThis.Api.sync_EndAction(Asc.c_oAscAsyncActionType.BlockInteraction, Asc.c_oAscAsyncAction.LoadImage);
|
||
};
|
||
}
|
||
}
|
||
|
||
this.put_Api = function(api)
|
||
{
|
||
this.Api = api;
|
||
|
||
if (this.Api.IsAsyncOpenDocumentImages !== undefined)
|
||
{
|
||
this.bIsAsyncLoadDocumentImages = this.Api.IsAsyncOpenDocumentImages();
|
||
if (this.bIsAsyncLoadDocumentImages)
|
||
{
|
||
if (undefined === this.Api.asyncImageEndLoadedBackground)
|
||
this.bIsAsyncLoadDocumentImages = false;
|
||
}
|
||
}
|
||
};
|
||
|
||
this.loadImageByUrl = function(image, url, isDisableCrypto)
|
||
{
|
||
if (this.isBlockchainSupport && (true !== isDisableCrypto))
|
||
image.preload_crypto(url);
|
||
else
|
||
image.src = url;
|
||
};
|
||
|
||
this.LoadDocumentImages = function (images, isCheckExists, syncImages) {
|
||
if (isCheckExists) {
|
||
for (let i = images.length - 1; i >= 0; i--) {
|
||
let id = AscCommon.getFullImageSrc2(images[i]);
|
||
if (this.map_image_index[id] && (this.map_image_index[id].Status === ImageLoadStatus.Complete)) {
|
||
images.splice(i, 1);
|
||
}
|
||
}
|
||
|
||
if (0 === images.length)
|
||
return;
|
||
}
|
||
|
||
// сначала заполним массив
|
||
|
||
const oRequiredSyncImages = {};
|
||
const arrImagesLoading = [];
|
||
for (let id in images) {
|
||
const sFullImageSrc = AscCommon.getFullImageSrc2(images[id]);
|
||
arrImagesLoading.push(sFullImageSrc);
|
||
if (syncImages && syncImages[images[id]]) {
|
||
oRequiredSyncImages[sFullImageSrc] = true;
|
||
}
|
||
}
|
||
if (syncImages) {
|
||
for (let id in syncImages) {
|
||
const sFullImageSrc = AscCommon.getFullImageSrc2(id);
|
||
if (!oRequiredSyncImages[sFullImageSrc]) {
|
||
arrImagesLoading.push(sFullImageSrc);
|
||
oRequiredSyncImages[sFullImageSrc] = true;
|
||
}
|
||
}
|
||
}
|
||
if (this.ThemeLoader == null)
|
||
this.Api.asyncImagesDocumentStartLoaded(arrImagesLoading);
|
||
else
|
||
this.ThemeLoader.asyncImagesStartLoaded(arrImagesLoading);
|
||
|
||
if (!this.bIsAsyncLoadDocumentImages) {
|
||
this._LoadImages(arrImagesLoading);
|
||
} else {
|
||
this._LoadImagesAsync(arrImagesLoading, oRequiredSyncImages);
|
||
}
|
||
};
|
||
|
||
this._LoadImages = function (arrImages) {
|
||
let fOnEachImageLoadCallback;
|
||
if (oThis.bIsLoadDocumentFirst === true) {
|
||
fOnEachImageLoadCallback = function () {
|
||
oThis.Api.OpenDocumentProgress.CurrentImage++;
|
||
oThis.Api.SendOpenProgress();
|
||
};
|
||
}
|
||
this.LoadImagesWithCallback(arrImages, function () {
|
||
if (oThis.ThemeLoader == null)
|
||
oThis.Api.asyncImagesDocumentEndLoaded();
|
||
else
|
||
oThis.ThemeLoader.asyncImagesEndLoaded();
|
||
}, [], false, fOnEachImageLoadCallback);
|
||
};
|
||
|
||
this._LoadImagesAsync = function (arrImages, oRequiredSyncImages) {
|
||
const arrAsyncImages = [];
|
||
const arrSyncImages = [];
|
||
for (let i = 0; i < arrImages.length; i += 1) {
|
||
if (oRequiredSyncImages[arrImages[i]]) {
|
||
arrSyncImages.push(arrImages[i]);
|
||
} else {
|
||
arrAsyncImages.push(arrImages[i]);
|
||
}
|
||
}
|
||
let fOnEachImageLoadCallback;
|
||
if (oThis.bIsLoadDocumentFirst === true) {
|
||
fOnEachImageLoadCallback = function () {
|
||
oThis.Api.OpenDocumentProgress.CurrentImage++;
|
||
oThis.Api.SendOpenProgress();
|
||
};
|
||
}
|
||
this.LoadImagesWithCallback(arrSyncImages, function () {
|
||
for (let i = 0; i < arrAsyncImages.length; i += 1) {
|
||
oThis.LoadImageAsync(arrAsyncImages[i]);
|
||
}
|
||
|
||
if (oThis.ThemeLoader == null)
|
||
oThis.Api.asyncImagesDocumentEndLoaded();
|
||
else
|
||
oThis.ThemeLoader.asyncImagesEndLoaded();
|
||
}, [], false, fOnEachImageLoadCallback);
|
||
};
|
||
|
||
this.LoadImage = function(src, type)
|
||
{
|
||
var image = this.map_image_index[src];
|
||
if (undefined != image)
|
||
return image;
|
||
|
||
this.Api.asyncImageStartLoaded();
|
||
|
||
var oImage = new CImage(src);
|
||
|
||
// просто прокидываем параметр
|
||
oImage.Type = type;
|
||
|
||
oImage.Image = new Image();
|
||
oImage.Status = ImageLoadStatus.Loading;
|
||
oThis.map_image_index[oImage.src] = oImage;
|
||
|
||
oImage.Image.onload = function() {
|
||
oImage.Status = ImageLoadStatus.Complete;
|
||
oThis.Api.asyncImageEndLoaded(oImage);
|
||
};
|
||
oImage.Image.onerror = function() {
|
||
oImage.Image = null;
|
||
oImage.Status = ImageLoadStatus.Complete;
|
||
oThis.Api.asyncImageEndLoaded(oImage);
|
||
};
|
||
AscCommon.backoffOnErrorImg(oImage.Image, function(img) {
|
||
// Remove crossOrigin on retry to maximize display success
|
||
img.crossOrigin = null;
|
||
oThis.loadImageByUrl(img, img.src);
|
||
});
|
||
// Enable CORS for cross-origin images to allow canvas manipulation
|
||
oImage.Image.crossOrigin = 'anonymous';
|
||
this.loadImageByUrl(oImage.Image, oImage.src);
|
||
return null;
|
||
};
|
||
|
||
this.LoadImageAsync = function(imgSrc)
|
||
{
|
||
var oImage = new CImage(imgSrc);
|
||
|
||
oImage.Status = ImageLoadStatus.Loading;
|
||
oImage.Image = new Image();
|
||
oThis.map_image_index[oImage.src] = oImage;
|
||
|
||
oImage.Image.onload = function() {
|
||
oImage.Status = ImageLoadStatus.Complete;
|
||
oThis.Api.asyncImageEndLoadedBackground(oImage);
|
||
};
|
||
oImage.Image.onerror = function() {
|
||
oImage.Status = ImageLoadStatus.Complete;
|
||
oImage.Image = null;
|
||
oThis.Api.asyncImageEndLoadedBackground(oImage);
|
||
};
|
||
AscCommon.backoffOnErrorImg(oImage.Image, function(img) {
|
||
// Remove crossOrigin on retry to maximize display success
|
||
img.crossOrigin = null;
|
||
oThis.loadImageByUrl(img, img.src);
|
||
});
|
||
// Enable CORS for cross-origin images to allow canvas manipulation
|
||
oImage.Image.crossOrigin = 'anonymous';
|
||
oThis.loadImageByUrl(oImage.Image, oImage.src);
|
||
};
|
||
|
||
this.LoadImagesWithCallback = function(arr, loadImageCallBack, loadImageCallBackArgs, isDisableCrypto, onEachImageLoadCallback)
|
||
{
|
||
let arrAsync = [];
|
||
for (let i = 0; i < arr.length; i++)
|
||
{
|
||
if (this.map_image_index[arr[i]] && (this.map_image_index[arr[i]].Status === ImageLoadStatus.Complete))
|
||
continue;
|
||
|
||
arrAsync.push(arr[i]);
|
||
}
|
||
|
||
if (arrAsync.length == 0)
|
||
{
|
||
loadImageCallBack.call(this.Api, loadImageCallBackArgs);
|
||
return;
|
||
}
|
||
|
||
let asyncImageCounter = arrAsync.length;
|
||
const callback = loadImageCallBack.bind(this.Api, loadImageCallBackArgs);
|
||
|
||
for (let i = 0; i < arrAsync.length; i++)
|
||
{
|
||
var oImage = new CImage(arrAsync[i]);
|
||
oImage.Image = new Image();
|
||
oImage.Image.parentImage = oImage;
|
||
oImage.Status = ImageLoadStatus.Loading;
|
||
this.map_image_index[oImage.src] = oImage;
|
||
|
||
oImage.Image.onload = function ()
|
||
{
|
||
this.parentImage.Status = ImageLoadStatus.Complete;
|
||
asyncImageCounter--;
|
||
onEachImageLoadCallback && onEachImageLoadCallback();
|
||
if (asyncImageCounter === 0)
|
||
callback();
|
||
};
|
||
oImage.Image.onerror = function ()
|
||
{
|
||
this.parentImage.Image = null;
|
||
this.parentImage.Status = ImageLoadStatus.Complete;
|
||
asyncImageCounter--;
|
||
onEachImageLoadCallback && onEachImageLoadCallback();
|
||
if (asyncImageCounter === 0)
|
||
callback();
|
||
};
|
||
AscCommon.backoffOnErrorImg(oImage.Image, function(img) {
|
||
// Remove crossOrigin on retry to maximize display success
|
||
img.crossOrigin = null;
|
||
oThis.loadImageByUrl(img, img.src);
|
||
});
|
||
// Enable CORS for cross-origin images to allow canvas manipulation
|
||
oImage.Image.crossOrigin = 'anonymous';
|
||
this.loadImageByUrl(oImage.Image, oImage.src, isDisableCrypto);
|
||
}
|
||
};
|
||
}
|
||
|
||
//---------------------------------------------------------export---------------------------------------------------
|
||
window['AscCommon'] = window['AscCommon'] || {};
|
||
window['AscCommon'].CGlobalFontLoader = CGlobalFontLoader;
|
||
window['AscCommon'].g_font_loader = new CGlobalFontLoader();
|
||
window['AscCommon'].g_image_loader = new CGlobalImageLoader();
|
||
})(window, window.document);
|