199 lines
6.8 KiB
JavaScript
Raw Normal View History

2024-10-25 18:09:59 +08:00
/* eslint-disable no-param-reassign */
2024-10-23 09:14:01 +08:00
import moduleHelper from '../module-helper';
import { formatJsonStr } from '../utils';
import fixCmapTable from './fix-cmap';
import readMetrics from './read-metrics';
import splitTTCToBufferOnlySC from './split-sc';
2024-10-25 18:09:59 +08:00
const { platform } = wx.getDeviceInfo();
2024-10-23 09:14:01 +08:00
const tempCacheObj = {};
let fontDataCache;
let getFontPromise;
let isReadFromCache = false;
const isIOS = platform === 'ios';
const isAndroid = platform === 'android';
const fontOptions = {
CJK_Unified_Ideographs: {
include: $CJK_Unified_Ideographs,
unicodeRange: [0x4E00, 0x9FFF],
},
C0_Controls_and_Basic_Latin: {
include: $C0_Controls_and_Basic_Latin,
unicodeRange: [0x0000, 0x007F],
},
CJK_Symbols_and_Punctuation: {
include: $CJK_Symbols_and_Punctuation,
unicodeRange: [0x3000, 0x303F],
},
General_Punctuation: {
include: $General_Punctuation,
unicodeRange: [0x2000, 0x206F],
},
Enclosed_CJK_Letters_and_Months: {
include: $Enclosed_CJK_Letters_and_Months,
unicodeRange: [0x3200, 0x32FF],
},
Vertical_Forms: {
include: $Vertical_Forms,
unicodeRange: [0xFE10, 0xFE1F],
},
CJK_Compatibility_Forms: {
include: $CJK_Compatibility_Forms,
unicodeRange: [0xFE30, 0xFE4F],
},
Miscellaneous_Symbols: {
include: $Miscellaneous_Symbols,
unicodeRange: [0x2600, 0x26FF],
},
CJK_Compatibility: {
include: $CJK_Compatibility,
unicodeRange: [0x3300, 0x33FF],
},
Halfwidth_and_Fullwidth_Forms: {
include: $Halfwidth_and_Fullwidth_Forms,
unicodeRange: [0xFF00, 0xFFEF],
},
Dingbats: {
include: $Dingbats,
unicodeRange: [0x2700, 0x27BF],
},
Letterlike_Symbols: {
include: $Letterlike_Symbols,
unicodeRange: [0x2100, 0x214F],
},
Enclosed_Alphanumerics: {
include: $Enclosed_Alphanumerics,
unicodeRange: [0x2460, 0x24FF],
},
Number_Forms: {
include: $Number_Forms,
unicodeRange: [0x2150, 0x218F],
},
Currency_Symbols: {
include: $Currency_Symbols,
unicodeRange: [0x20A0, 0x20CF],
},
Arrows: {
include: $Arrows,
unicodeRange: [0x2190, 0x21FF],
},
Geometric_Shapes: {
include: $Geometric_Shapes,
unicodeRange: [0x25A0, 0x25FF],
},
Mathematical_Operators: {
include: $Mathematical_Operators,
unicodeRange: [0x2200, 0x22FF],
},
CustomUnicodeRange: $CustomUnicodeRange,
};
2024-10-25 18:09:59 +08:00
function handleGetFontData(config, forceFallback) {
2024-10-23 09:14:01 +08:00
const canGetWxCommonFont = !!GameGlobal.manager?.font?.getCommonFont;
2024-10-25 18:09:59 +08:00
2024-10-23 09:14:01 +08:00
if (!config && !canGetWxCommonFont) {
return Promise.reject('invalid usage');
}
2024-10-25 18:09:59 +08:00
// eslint-disable-next-line @typescript-eslint/no-misused-promises
if (!getFontPromise || forceFallback) {
2024-10-23 09:14:01 +08:00
getFontPromise = new Promise((resolve, reject) => {
2024-10-25 18:09:59 +08:00
if ((!canGetWxCommonFont || forceFallback) && !!config) {
2024-10-23 09:14:01 +08:00
const xhr = new GameGlobal.unityNamespace.UnityLoader.UnityCache.XMLHttpRequest();
2024-10-25 18:09:59 +08:00
xhr.open('GET', config.fallbackUrl, true);
xhr.responseType = 'arraybuffer';
2024-10-23 09:14:01 +08:00
xhr.onload = () => {
2024-10-25 18:09:59 +08:00
2024-10-23 09:14:01 +08:00
if ((xhr.status === 200 || xhr.status === 0) && xhr.response) {
2024-10-25 18:09:59 +08:00
const notoFontData = xhr.response;
fontDataCache = notoFontData;
isReadFromCache = xhr.isReadFromCache;
resolve();
2024-10-23 09:14:01 +08:00
}
};
2024-10-25 18:09:59 +08:00
xhr.onerror = reject;
xhr.send();
2024-10-23 09:14:01 +08:00
return;
}
2024-10-25 18:09:59 +08:00
let unicodeRange = [];
2024-10-23 09:14:01 +08:00
Object.keys(fontOptions).forEach((key) => {
if (fontOptions[key].include) {
2024-10-25 18:09:59 +08:00
unicodeRange.push(fontOptions[key].unicodeRange);
2024-10-23 09:14:01 +08:00
}
});
2024-10-25 18:09:59 +08:00
unicodeRange = unicodeRange.concat(fontOptions.CustomUnicodeRange);
2024-10-23 09:14:01 +08:00
GameGlobal.manager.font.getCommonFont({
success(fontData) {
if (isIOS) {
fixCmapTable(fontData);
}
2024-10-25 18:09:59 +08:00
2024-10-23 09:14:01 +08:00
if (isAndroid) {
const tempData = splitTTCToBufferOnlySC(fontData);
if (tempData) {
2024-10-25 18:09:59 +08:00
fontData = tempData;
2024-10-23 09:14:01 +08:00
}
}
2024-10-25 18:09:59 +08:00
fontDataCache = fontData;
resolve();
2024-10-23 09:14:01 +08:00
},
2024-10-25 18:09:59 +08:00
fail: reject,
}, unicodeRange);
2024-10-23 09:14:01 +08:00
});
}
2024-10-25 18:09:59 +08:00
return getFontPromise;
2024-10-23 09:14:01 +08:00
}
2024-10-25 18:09:59 +08:00
function WXGetFontRawData(conf, callbackId, forceFallback = false) {
const config = formatJsonStr(conf);
const loadFromRemote = !GameGlobal.manager?.font?.getCommonFont;
GameGlobal.manager.TimeLogger.timeStart('WXGetFontRawData');
handleGetFontData(config, forceFallback).then(() => {
2024-10-23 09:14:01 +08:00
if (fontDataCache) {
2024-10-25 18:09:59 +08:00
GameGlobal.manager.font.reportGetFontCost(GameGlobal.manager.TimeLogger.timeEnd('WXGetFontRawData'), { loadFromRemote: forceFallback || loadFromRemote, isReadFromCache, preloadWXFont: GameGlobal.unityNamespace.preloadWXFont });
const { ascent, descent, lineGap, unitsPerEm } = readMetrics(fontDataCache) || {};
tempCacheObj[callbackId] = fontDataCache;
2024-10-23 09:14:01 +08:00
moduleHelper.send('GetFontRawDataCallback', JSON.stringify({ callbackId, type: 'success', res: JSON.stringify({ byteLength: fontDataCache.byteLength, ascent, descent, lineGap, unitsPerEm }) }));
2024-10-25 18:09:59 +08:00
GameGlobal.manager.Logger.pluginLog(`[font] load font from ${forceFallback || loadFromRemote ? `network, url=${config.fallbackUrl}` : 'local'}`);
2024-10-23 09:14:01 +08:00
2024-10-25 18:09:59 +08:00
fontDataCache = null;
2024-10-23 09:14:01 +08:00
}
else {
GameGlobal.manager.Logger.pluginError('[font] load font error: empty content');
}
})
.catch((err) => {
2024-10-25 18:09:59 +08:00
if (err.errmsg === 'no support font' && forceFallback === false) {
WXGetFontRawData(conf, callbackId, true);
}
else {
GameGlobal.manager.Logger.pluginError('[font] load font error: ', err);
}
2024-10-23 09:14:01 +08:00
});
}
function WXShareFontBuffer(buffer, offset, callbackId) {
if (typeof tempCacheObj[callbackId] === 'string') {
GameGlobal.manager.Logger.pluginError('[font]内存写入异常');
}
buffer.set(new Uint8Array(tempCacheObj[callbackId]), offset);
delete tempCacheObj[callbackId];
}
export function preloadWxCommonFont() {
if (!!GameGlobal.unityNamespace.preloadWXFont && !!GameGlobal.manager?.font?.getCommonFont) {
handleGetFontData();
}
}
export default {
WXGetFontRawData,
WXShareFontBuffer,
};