Skip to content

Commit

Permalink
fix(android, ios): improve dynamically load font according to code re…
Browse files Browse the repository at this point in the history
…view
  • Loading branch information
Cyunong committed Oct 24, 2024
1 parent c13fda7 commit d587327
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,9 @@ public void destroy() {
@Override
public void loadFontAndRefreshWindow(@NonNull String fontFamily, @NonNull String fontUrl,
int rootId, Object promise) {
if (!(promise instanceof Promise)) {
promise = null;
}
Promise pm = (promise instanceof Promise) ? ((Promise) promise) : null;
if (mRenderer != null) {
mRenderer.loadFontAndRefreshWindow(fontFamily, fontUrl, rootId, (Promise) promise);
mRenderer.loadFontAndRefreshWindow(fontFamily, fontUrl, rootId, pm);
}
}

Expand Down
6 changes: 3 additions & 3 deletions framework/ios/module/fontLoader/HippyFontLoaderModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ typedef NS_ENUM(NSInteger, HippyFontUrlState) {
* @param url - The font url needs to download from.
* @return Yes if the font is downloading from the url.
*/
+ (BOOL) isUrlLoading:(NSString *)url;
+ (BOOL)isUrlLoading:(NSString *)url;

/**
* Get the serial queue in HippyFontLoaderModule for asyn serial operations.
*
* @return The serial dispatch_queue_t.
*/
+ (dispatch_queue_t) getFontSerialQueue;
+ (dispatch_queue_t)getFontSerialQueue;

/**
* Load font from the url.
Expand All @@ -72,7 +72,7 @@ typedef NS_ENUM(NSInteger, HippyFontUrlState) {
* @param resolve - The callback block for downloading successful.
* @param reject - The callback block for downloading failed.
*/
- (void) load:(NSString *)fontFamily from:(NSString *)urlString resolver:(nullable HippyPromiseResolveBlock)resolve rejecter:(nullable HippyPromiseRejectBlock)reject;
- (void)load:(NSString *)fontFamily from:(NSString *)urlString resolver:(nullable HippyPromiseResolveBlock)resolve rejecter:(nullable HippyPromiseRejectBlock)reject;

@end

Expand Down
8 changes: 4 additions & 4 deletions framework/ios/module/fontLoader/HippyFontLoaderModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -76,19 +76,19 @@ - (instancetype)init {
return self;
}

+ (dispatch_queue_t) getFontSerialQueue {
+ (dispatch_queue_t)getFontSerialQueue {
return serialQueue;
}

+ (void) setUrl:(NSString *)url state:(HippyFontUrlState)state {
+ (void)setUrl:(NSString *)url state:(HippyFontUrlState)state {
[urlLoadState setObject:@(state) forKey:url];
}

+ (BOOL) isUrlLoading:(NSString *)url {
+ (BOOL)isUrlLoading:(NSString *)url {
return [[urlLoadState objectForKey:url] integerValue] == HippyFontUrlLoading;
}

+ (void) initDictIfNeeded {
+ (void)initDictIfNeeded {
if (fontFamilyToFiles == nil) {
fontFamilyToFiles = [NSMutableDictionary dictionaryWithContentsOfFile:fontFamilySavePath];
if (fontFamilyToFiles == nil) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobject GetNativeRendererInstance(JNIEnv* j_env,
jint j_render_manager_id);


void RefreshTextWindow(JNIEnv *j_env, jobject j_object, jint j_render_manager_id, jint j_root_id);
void OnFontLoaded(JNIEnv *j_env, jobject j_object, jint j_render_manager_id, jint j_root_id);

void UpdateRootSize(JNIEnv* j_env, jobject j_obj, jint j_render_manager_id, jint j_root_id,
jfloat width, jfloat height);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ REGISTER_JNI("com/tencent/renderer/NativeRenderProvider",
UpdateRootSize)

REGISTER_JNI("com/tencent/renderer/NativeRenderProvider",
"refreshTextWindow",
"onFontLoaded",
"(II)V",
RefreshTextWindow)
OnFontLoaded)

static jint JNI_OnLoad(__unused JavaVM* j_vm, __unused void* reserved) {
auto j_env = JNIEnvironment::GetInstance()->AttachCurrentThread();
Expand Down Expand Up @@ -168,25 +168,25 @@ void MarkTextNodeDirtyRecursive(const std::shared_ptr<DomNode>& node) {
}
}

void RefreshTextWindow(JNIEnv *j_env, jobject j_object, jint j_render_manager_id, jint j_root_id) {
void OnFontLoaded(JNIEnv *j_env, jobject j_object, jint j_render_manager_id, jint j_root_id) {
auto& map = NativeRenderManager::PersistentMap();
std::shared_ptr<NativeRenderManager> render_manager;
bool ret = map.Find(static_cast<uint32_t>(j_render_manager_id), render_manager);
if (!ret) {
FOOTSTONE_DLOG(WARNING) << "RefreshTextWindow j_render_manager_id invalid";
FOOTSTONE_DLOG(WARNING) << "OnFontLoaded j_render_manager_id invalid";
return;
}
std::shared_ptr<DomManager> dom_manager = render_manager->GetDomManager();
if (dom_manager == nullptr) {
FOOTSTONE_DLOG(WARNING) << "RefreshTextWindow dom_manager is nullptr";
FOOTSTONE_DLOG(WARNING) << "OnFontLoaded dom_manager is nullptr";
return;
}
auto& root_map = RootNode::PersistentMap();
std::shared_ptr<RootNode> root_node;
uint32_t root_id = footstone::check::checked_numeric_cast<jint, uint32_t>(j_root_id);
ret = root_map.Find(root_id, root_node);
if (!ret) {
FOOTSTONE_DLOG(WARNING) << "RefreshTextWindow root_node is nullptr";
FOOTSTONE_DLOG(WARNING) << "OnFontLoaded root_node is nullptr";
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.Executor;

@SuppressWarnings({"deprecation", "unused"})
public class HippyTextInput extends AppCompatEditText implements HippyViewBase,
Expand Down Expand Up @@ -100,7 +101,7 @@ public class HippyTextInput extends AppCompatEditText implements HippyViewBase,
private String mFontFamily;
private String mFontUrl;
private Paint mTextPaint;
protected boolean mFromFontLoader = false;
private FontLoader.FontLoadState mFontLoadState;

public HippyTextInput(Context context) {
super(context);
Expand Down Expand Up @@ -214,9 +215,10 @@ public void onBatchComplete() {
if (nativeRenderer != null) {
fontLoader = nativeRenderer.getFontLoader();
}
if (!mFromFontLoader && fontLoader != null && fontLoader.isFontLoaded(mFontFamily)) {
if (mFontLoadState == FontLoader.FontLoadState.FONT_UNLOAD && fontLoader != null &&
fontLoader.isFontLoaded(mFontFamily)) {
mShouldUpdateTypeface = true;
mFromFontLoader = true;
mFontLoadState = FontLoader.FontLoadState.FONT_LOADED;
}
if (mShouldUpdateTypeface) {
updateTypeface();
Expand Down Expand Up @@ -776,8 +778,8 @@ public void setFontFamily(String family) {
if (nativeRenderer != null) {
fontLoader = nativeRenderer.getFontLoader();
}
if (mFromFontLoader && fontLoader != null && !fontLoader.isFontLoaded(mFontFamily)) {
mFromFontLoader = false;
if (fontLoader != null && !fontLoader.isFontLoaded(mFontFamily)) {
mFontLoadState = FontLoader.FontLoadState.FONT_UNLOAD;
}
}
}
Expand All @@ -803,17 +805,16 @@ private void updateTypeface() {
mTextPaint.reset();
}
NativeRender nativeRenderer = NativeRendererManager.getNativeRenderer(getContext());
if (mFontUrl != null && !mFontUrl.isEmpty()) {
if (!TextUtils.isEmpty(mFontUrl)) {
FontLoader loader = nativeRenderer == null ? null : nativeRenderer.getFontLoader();
if (loader != null) {
int rootId = nativeRenderer.getRootView(this).getId();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Executor executor = nativeRenderer.getBackgroundExecutor();
if (executor != null) {
executor.execute(() -> {
loader.loadIfNeeded(mFontFamily, mFontUrl, rootId);
}
});
thread.start();
});
}
}
}
FontAdapter fontAdapter = nativeRenderer == null ? null : nativeRenderer.getFontAdapter();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ VirtualNode createVirtualNode(int rootId, int id, int pid, int index, @NonNull S

void onSizeChanged(int rootId, int nodeId, int width, int height, boolean isSync);

void refreshTextWindow(int rootId);
void onFontLoaded(int rootId);

void updateDimension(int width, int height);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,8 +337,8 @@ public void onSizeChanged(int rootId, int width, int height) {
updateRootSize(mInstanceId, rootId, PixelUtil.px2dp(width), PixelUtil.px2dp(height));
}

public void refreshTextWindow(int rootId) {
refreshTextWindow(mInstanceId, rootId);
public void onFontLoaded(int rootId) {
onFontLoaded(mInstanceId, rootId);
}

public void onSizeChanged(int rootId, int nodeId, int width, int height, boolean isSync) {
Expand Down Expand Up @@ -445,7 +445,7 @@ private void dispatchEventImpl(int rootId, int nodeId, @NonNull String eventName
* @param instanceId the unique id of native (C++) render manager
*/
@SuppressWarnings("JavaJniMissingFunction")
private native void refreshTextWindow(int instanceId, int rootId);
private native void onFontLoaded(int instanceId, int rootId);

/**
* Updates the size to the specified node, such as modal node, should set new window size before
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,8 @@ public ImageLoaderAdapter getImageLoader() {
return mImageLoader;
}

@Nullable
public FontLoader getFontLoader() {
if (mFontLoader == null && getVfsManager() != null) {
if (mFontLoader == null) {
mFontLoader = new FontLoader(getVfsManager(), this);
}
return mFontLoader;
Expand Down Expand Up @@ -416,8 +415,8 @@ private void onSizeChanged(int rootId, int w, int h) {
mRenderProvider.onSizeChanged(rootId, w, h);
}

public void refreshTextWindow(int rootId) {
mRenderProvider.refreshTextWindow(rootId);
public void onFontLoaded(int rootId) {
mRenderProvider.onFontLoaded(rootId);
}

@Override
Expand Down Expand Up @@ -1144,7 +1143,7 @@ private boolean collectNodeInfo(@NonNull RenderNode child, int pid, int outerLef
@Override
public void loadFontAndRefreshWindow(@NonNull String fontFamily, @NonNull String fontUrl,
int rootId, final Promise promise) {
if (mFontLoader == null && getVfsManager() != null) {
if (mFontLoader == null) {
mFontLoader = new FontLoader(getVfsManager(), this);
}
mFontLoader.loadAndRefresh(fontFamily, fontUrl, rootId, promise);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@ public class FontLoader {
private static final String LOCAL_FONT_PATH_MAP_NAME = "localFontPathMap.ser";

public enum FontLoadState {
FONT_UNLOAD,
FONT_LOADING,
FONT_LOADED
FONT_LOADED,
}


Expand Down Expand Up @@ -193,6 +194,9 @@ private void initMapIfNeeded() {

public boolean loadIfNeeded(final String fontFamily, final String fontUrl, int rootId) {
initMapIfNeeded();
if (TextUtils.isEmpty(fontFamily) || TextUtils.isEmpty(fontUrl)) {
return false;
}
String fontFileName = mConcurrentUrlFontMap.get(fontUrl);
if (fontFileName != null) {
if (fontFileName.startsWith(PREFIX_ASSETS) && isAssetFileExists(fontFileName)) {
Expand All @@ -206,7 +210,8 @@ public boolean loadIfNeeded(final String fontFamily, final String fontUrl, int r
return false;
}
}
if (mConcurrentFontLoadStateMap.containsKey(fontFamily)) {
FontLoadState state = mConcurrentFontLoadStateMap.get(fontFamily);
if (state == FontLoadState.FONT_LOADING || state == FontLoadState.FONT_LOADED) {
return false;
}
loadAndRefresh(fontFamily, fontUrl, rootId, null);
Expand All @@ -225,6 +230,12 @@ public void loadAndRefresh(final String fontFamily, final String fontUrl, int ro
}
mConcurrentFontLoadStateMap.put(fontFamily, FontLoadState.FONT_LOADING);
String convertFontUrl = convertToLocalPathIfNeeded(fontUrl);
if (mVfsManager.get() == null) {
if (promise != null) {
promise.reject("Get vfsManager failed!");
}
return;
}
mVfsManager.get().fetchResourceAsync(convertFontUrl, null, null,
new FetchResourceCallback() {
@Override
Expand All @@ -233,7 +244,7 @@ public void onFetchCompleted(@NonNull final ResourceDataHolder dataHolder) {
if (dataHolder.resultCode
!= ResourceDataHolder.RESOURCE_LOAD_SUCCESS_CODE || bytes == null
|| bytes.length <= 0) {
mConcurrentFontLoadStateMap.remove(fontFamily);
mConcurrentFontLoadStateMap.put(fontFamily, FontLoadState.FONT_UNLOAD);
if (promise != null) {
promise.reject("Fetch font file failed, url=" + fontUrl);
}
Expand Down Expand Up @@ -273,7 +284,7 @@ public void onFetchCompleted(@NonNull final ResourceDataHolder dataHolder) {
TypeFaceUtil.clearFontCache(fontFamily);
NativeRender nativeRender = mNativeRenderRef.get();
if (nativeRender != null && needRefresh) {
nativeRender.refreshTextWindow(rootId);
nativeRender.onFontLoaded(rootId);
}
}
dataHolder.recycle();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@
import android.text.style.AbsoluteSizeSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.ImageSpan;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import com.tencent.mtt.hippy.annotation.HippyControllerProps;
import com.tencent.mtt.hippy.dom.node.NodeProps;
import com.tencent.mtt.hippy.utils.I18nUtil;
Expand All @@ -63,6 +65,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;

public class TextVirtualNode extends VirtualNode {

Expand Down Expand Up @@ -117,7 +120,8 @@ public class TextVirtualNode extends VirtualNode {
protected String mFontUrl;
@Nullable
protected WeakReference<FontLoader> mFontLoaderRef;
protected boolean mFromFontLoader = false;
protected WeakReference<NativeRender> mNativeRenderRef;
protected FontLoader.FontLoadState mFontLoadState;
@Nullable
protected SpannableStringBuilder mSpanned;
@Nullable
Expand All @@ -139,6 +143,7 @@ public TextVirtualNode(int rootId, int id, int pid, int index,
super(rootId, id, pid, index);
mFontAdapter = nativeRender.getFontAdapter();
mFontLoaderRef = new WeakReference<>(nativeRender.getFontLoader());
mNativeRenderRef = new WeakReference<>(nativeRender);
if (I18nUtil.isRTL()) {
mAlignment = Layout.Alignment.ALIGN_OPPOSITE;
}
Expand Down Expand Up @@ -188,6 +193,9 @@ public void setFontFamily(String family) {
if (!Objects.equals(mFontFamily, family)) {
mFontFamily = family;
markDirty();
if (mFontLoaderRef.get() != null && !mFontLoaderRef.get().isFontLoaded(mFontFamily)) {
mFontLoadState = FontLoader.FontLoadState.FONT_UNLOAD;
}
}
}

Expand Down Expand Up @@ -488,14 +496,15 @@ protected void createSpanOperationImpl(@NonNull List<SpanOperation> ops,
if (mFontAdapter != null && mEnableScale) {
size = (int) (size * mFontAdapter.getFontScale());
}
if (mFontUrl != null && !mFontUrl.isEmpty() && mFontLoaderRef.get() != null) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
mFontLoaderRef.get().loadIfNeeded(mFontFamily, mFontUrl, getRootId());
if (!TextUtils.isEmpty(mFontUrl) && mFontLoaderRef.get() != null) {
if (mNativeRenderRef.get() != null) {
Executor executor = mNativeRenderRef.get().getBackgroundExecutor();
if (executor != null) {
executor.execute(() -> {
mFontLoaderRef.get().loadIfNeeded(mFontFamily, mFontUrl, getRootId());
});
}
});
thread.start();
}
}
ops.add(new SpanOperation(start, end, new AbsoluteSizeSpan(size)));
ops.add(new SpanOperation(start, end, new TextStyleSpan(mItalic, mFontWeight, mFontFamily, mFontAdapter)));
Expand Down Expand Up @@ -564,9 +573,10 @@ protected Layout createLayout() {
@NonNull
protected Layout createLayout(final float width, final FlexMeasureMode widthMode) {
FontLoader fontLoader = mFontLoaderRef.get();
if (!mFromFontLoader && fontLoader != null && fontLoader.isFontLoaded(mFontFamily)) {
if (mFontLoadState == FontLoader.FontLoadState.FONT_UNLOAD && fontLoader != null &&
fontLoader.isFontLoaded(mFontFamily)) {
mDirty = true;
mFromFontLoader = true;
mFontLoadState = FontLoader.FontLoadState.FONT_LOADED;
}
if (mSpanned == null || mDirty) {
mSpanned = createSpan(true);
Expand Down

0 comments on commit d587327

Please sign in to comment.