From 370f9ab2ad4bf7664016bdc1d6bf3d4b27a5177e Mon Sep 17 00:00:00 2001 From: arnonchen <745735906@qq.com> Date: Tue, 22 Oct 2024 11:22:29 +0800 Subject: [PATCH] fix(android, react, vue): add font load state, change resolve from void to string --- .../src/modules/FontLoader/index.jsx | 4 +- .../native-demos/demo-vue-native.vue | 3 +- .../native-demo/demo-vue-native.vue | 3 +- .../src/runtime/native/index.ts | 4 +- .../native-modules/font-loader-module.ts | 2 +- .../packages/hippy-vue/src/runtime/native.ts | 2 +- .../renderer/component/text/FontLoader.java | 65 ++++++++++--------- 7 files changed, 43 insertions(+), 40 deletions(-) diff --git a/driver/js/examples/hippy-react-demo/src/modules/FontLoader/index.jsx b/driver/js/examples/hippy-react-demo/src/modules/FontLoader/index.jsx index 4828686db3a..f204779e6f7 100644 --- a/driver/js/examples/hippy-react-demo/src/modules/FontLoader/index.jsx +++ b/driver/js/examples/hippy-react-demo/src/modules/FontLoader/index.jsx @@ -77,8 +77,8 @@ export default class LoadFontExample extends React.Component { async loadFont() { this.setState({ fontFamily: this.state.inputFontFamily }); await FontLoaderModule.load(this.state.fontFamily, this.state.fontUrl) - .then(() => { - this.setState({ loadState: 'Success' }); + .then((result) => { + this.setState({ loadState: result }); }) .catch((error) => { this.setState({ loadState: error }); diff --git a/driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-vue-native.vue b/driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-vue-native.vue index aa1c99eb72d..622a555e6f2 100644 --- a/driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-vue-native.vue +++ b/driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-vue-native.vue @@ -454,8 +454,7 @@ export default { console.log('fontUrl:', this.fontUrl) let result; try { - await Vue.Native.FontLoader.load(this.fontFamily, this.fontUrl); - result = 'success'; + result = await Vue.Native.FontLoader.load(this.fontFamily, this.fontUrl); } catch (error) { result = error.message; } diff --git a/driver/js/examples/hippy-vue-next-demo/src/components/native-demo/demo-vue-native.vue b/driver/js/examples/hippy-vue-next-demo/src/components/native-demo/demo-vue-native.vue index e1fad9a0ab4..f62d7ec52f9 100644 --- a/driver/js/examples/hippy-vue-next-demo/src/components/native-demo/demo-vue-native.vue +++ b/driver/js/examples/hippy-vue-next-demo/src/components/native-demo/demo-vue-native.vue @@ -429,8 +429,7 @@ export default defineComponent({ console.log('load fontUrl:', fontUrl.value) let result; try { - await Native.FontLoader.load(fontFamily.value, fontUrl.value); - result = 'success'; + result = await Native.FontLoader.load(fontFamily.value, fontUrl.value); } catch (error) { result = error.message; } diff --git a/driver/js/packages/hippy-vue-next/src/runtime/native/index.ts b/driver/js/packages/hippy-vue-next/src/runtime/native/index.ts index c6eaba00f19..14a910bf969 100644 --- a/driver/js/packages/hippy-vue-next/src/runtime/native/index.ts +++ b/driver/js/packages/hippy-vue-next/src/runtime/native/index.ts @@ -242,7 +242,7 @@ export interface NativeApiType { }; FontLoader: { - load: (fontFamily: string, url: string) => Promise; + load: (fontFamily: string, url: string) => Promise; }; // include window and screen info @@ -528,7 +528,7 @@ export const Native: NativeApiType = { * @param fontFamily * @param url - font url */ - load(fontFamily, url): Promise { + load(fontFamily: string, url: string): Promise { return Native.callNativeWithPromise.call( this, 'FontLoaderModule', diff --git a/driver/js/packages/hippy-vue-next/src/types/native-modules/font-loader-module.ts b/driver/js/packages/hippy-vue-next/src/types/native-modules/font-loader-module.ts index 16de6f1d1a3..73cbbd664e3 100644 --- a/driver/js/packages/hippy-vue-next/src/types/native-modules/font-loader-module.ts +++ b/driver/js/packages/hippy-vue-next/src/types/native-modules/font-loader-module.ts @@ -19,5 +19,5 @@ */ export interface FontLoaderModule { - load: (fontFamily: string, url: string) => undefined; + load: (fontFamily: string, url: string) => string; } diff --git a/driver/js/packages/hippy-vue/src/runtime/native.ts b/driver/js/packages/hippy-vue/src/runtime/native.ts index ab61d08a463..8d1966a8622 100644 --- a/driver/js/packages/hippy-vue/src/runtime/native.ts +++ b/driver/js/packages/hippy-vue/src/runtime/native.ts @@ -453,7 +453,7 @@ const Native: NeedToTyped = { * @param {string} fontFamily - The font family to download, * @param {string} url - The url where to download the font. */ - load(fontFamily: NeedToTyped, url: NeedToTyped) { + load(fontFamily: string, url: string) { return callNativeWithPromise.call(this, 'FontLoaderModule', 'load', fontFamily, url); }, }, diff --git a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/FontLoader.java b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/FontLoader.java index a6898ac40dd..b830fdd0e3a 100644 --- a/renderer/native/android/src/main/java/com/tencent/renderer/component/text/FontLoader.java +++ b/renderer/native/android/src/main/java/com/tencent/renderer/component/text/FontLoader.java @@ -38,31 +38,32 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArraySet; public class FontLoader { private final WeakReference mNativeRenderRef; private final WeakReference mVfsManager; private final File mFontDir; - private final File mFontUrlDictPath; - private Map mConcurrentFontUrlDict; - private final Set mConcurrentFontsLoaded; - private final Set mConcurrentUrlsLoading; + private final File mFontUrlMapPath; + private Map mConcurrentFontUrlMap; + private final Map mConcurrentFontLoadStateMap; private static final String[] ALLOWED_EXTENSIONS = {"otf", "ttf"}; private static final String FONT_DIR_NAME = "HippyFonts"; - private static final String FONT_URL_DICT_NAME = "fontUrlDict.ser"; + private static final String FONT_URL_MAP_NAME = "fontUrlMap.ser"; + + public enum FontLoadState { + FONT_LOADING, + FONT_LOADED + } public FontLoader(VfsManager vfsManager, NativeRender nativeRender) { mNativeRenderRef = new WeakReference<>(nativeRender); mVfsManager = new WeakReference<>(vfsManager); mFontDir = new File(ContextHolder.getAppContext().getCacheDir(), FONT_DIR_NAME); - mFontUrlDictPath = new File(mFontDir, FONT_URL_DICT_NAME); - mConcurrentFontsLoaded = new CopyOnWriteArraySet<>(); - mConcurrentUrlsLoading = new CopyOnWriteArraySet<>(); + mFontUrlMapPath = new File(mFontDir, FONT_URL_MAP_NAME); + mConcurrentFontLoadStateMap = new ConcurrentHashMap<>(); } private boolean saveFontFile(byte[] byteArray, String fileName, Promise promise) { @@ -78,7 +79,7 @@ private boolean saveFontFile(byte[] byteArray, String fileName, Promise promise) try (FileOutputStream fos = new FileOutputStream(fontFile)) { fos.write(byteArray); if (promise != null) { - promise.resolve(null); + promise.resolve(fileName + " download success!"); } return true; } catch (IOException e) { @@ -90,16 +91,17 @@ private boolean saveFontFile(byte[] byteArray, String fileName, Promise promise) } public boolean isFontLoaded(String fontFamily) { - return mConcurrentFontsLoaded.contains(fontFamily); + return fontFamily != null && + mConcurrentFontLoadStateMap.get(fontFamily) == FontLoadState.FONT_LOADED; } - private void saveFontUrlDictFile() { - try (FileOutputStream fos = new FileOutputStream(mFontUrlDictPath); + private void saveFontUrlMapFile() { + try (FileOutputStream fos = new FileOutputStream(mFontUrlMapPath); ObjectOutputStream oos = new ObjectOutputStream(fos)) { - oos.writeObject(mConcurrentFontUrlDict); - LogUtils.d("FontLoader", "Save fontUrlDict.ser success"); + oos.writeObject(mConcurrentFontUrlMap); + LogUtils.d("FontLoader", "Save fontUrlMap.ser success"); } catch (IOException e) { - LogUtils.d("FontLoader", "Save fontUrlDict.ser failed"); + LogUtils.d("FontLoader", "Save fontUrlMap.ser failed"); } } @@ -115,24 +117,24 @@ public static String getFileExtension(String url) { } public boolean loadIfNeeded(final String fontFamily, final String fontUrl, int rootId) { - if (mConcurrentFontUrlDict == null) { - Map fontUrlDict; - try (FileInputStream fis = new FileInputStream(mFontUrlDictPath); + if (mConcurrentFontUrlMap == null) { + Map fontUrlMap; + try (FileInputStream fis = new FileInputStream(mFontUrlMapPath); ObjectInputStream ois = new ObjectInputStream(fis)) { - fontUrlDict = (Map) ois.readObject(); + fontUrlMap = (Map) ois.readObject(); } catch (IOException | ClassNotFoundException e) { - fontUrlDict = new HashMap<>(); + fontUrlMap = new HashMap<>(); } - mConcurrentFontUrlDict = new ConcurrentHashMap<>(fontUrlDict); + mConcurrentFontUrlMap = new ConcurrentHashMap<>(fontUrlMap); } - String fontFileName = mConcurrentFontUrlDict.get(fontUrl); + String fontFileName = mConcurrentFontUrlMap.get(fontUrl); if (fontFileName != null) { File fontFile = new File(mFontDir, fontFileName); if (fontFile.exists()) { return false; } } - if (mConcurrentUrlsLoading.contains(fontUrl)) { + if (mConcurrentFontLoadStateMap.containsKey(fontFamily)) { return false; } loadAndRefresh(fontFamily, fontUrl, rootId, null); @@ -149,7 +151,7 @@ public void loadAndRefresh(final String fontFamily, final String fontUrl, int ro } return; } - mConcurrentUrlsLoading.add(fontUrl); + mConcurrentFontLoadStateMap.put(fontFamily, FontLoadState.FONT_LOADING); mVfsManager.get().fetchResourceAsync(fontUrl, null, null, new FetchResourceCallback() { @Override @@ -158,6 +160,7 @@ public void onFetchCompleted(@NonNull final ResourceDataHolder dataHolder) { if (dataHolder.resultCode != ResourceDataHolder.RESOURCE_LOAD_SUCCESS_CODE || bytes == null || bytes.length <= 0) { + mConcurrentFontLoadStateMap.remove(fontFamily); if (promise != null) { promise.reject("Fetch font file failed, url=" + fontUrl); } @@ -165,17 +168,19 @@ public void onFetchCompleted(@NonNull final ResourceDataHolder dataHolder) { String fileName = fontFamily + getFileExtension(fontUrl); if (saveFontFile(bytes, fileName, promise)) { LogUtils.d("FontLoader", "Fetch font file success"); - mConcurrentFontsLoaded.add(fontFamily); - mConcurrentFontUrlDict.put(fontUrl, fileName); - saveFontUrlDictFile(); + mConcurrentFontLoadStateMap.put(fontFamily, FontLoadState.FONT_LOADED); + mConcurrentFontUrlMap.put(fontUrl, fileName); + saveFontUrlMapFile(); TypeFaceUtil.clearFontCache(fontFamily); NativeRender nativeRender = mNativeRenderRef.get(); if (nativeRender != null) { nativeRender.refreshTextWindow(rootId); } } + else { + mConcurrentFontLoadStateMap.remove(fontFamily); + } } - mConcurrentUrlsLoading.remove(fontUrl); dataHolder.recycle(); }