Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

package com.facebook.react.views.text;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -42,10 +43,12 @@ public class ReactFontManager {

final private Map<String, FontFamily> mFontCache;
final private Map<String, Typeface> mCustomTypefaceCache;
final private Map<String, Typeface> mFontFileNameTypefaceCache;

private ReactFontManager() {
mFontCache = new HashMap<>();
mCustomTypefaceCache = new HashMap<>();
mFontFileNameTypefaceCache = new HashMap<>();
}

public static ReactFontManager getInstance() {
Expand All @@ -62,6 +65,21 @@ public static ReactFontManager getInstance() {
return getTypeface(fontFamilyName, style, 0, assetManager);
}

public @Nullable Typeface getTypeface(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we instead extend the existing addCustomFont method, to have another override which takes a Typeface directly? That way we are not introducing another font loading path. -- it'll be a smaller diff from the OSS version, and we can look at upstreaming that change to OSS?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I will have a look at this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I understood from the flow.
If I add an overridden addCustomFont method which accepts Typeface, this typeface should also be created for which we require our createTypeface method. And in addCustomFont we will have to add this typeface to map(cache) for faster access later. Whenever any component needs to apply this typeface, they will have to use getTypeface method which will return the typeface from the map. This flow will not remove the methods we added but instead add one more method to this class.
Please correct me if wrong as I may not have understood your point properly.

String fontPath,
String fontFamilyName,
int style) {
String fileName = fontPath.substring(fontPath.lastIndexOf(File.separator) + 1);
Typeface typeface = mFontFileNameTypefaceCache.get(fileName);
if (typeface == null) {
typeface = createTypeface(fontPath, fontFamilyName, style);
if (typeface != null) {
mFontFileNameTypefaceCache.put(fileName, typeface);
}
}
return typeface;
}

public @Nullable Typeface getTypeface(
String fontFamilyName,
int style,
Expand Down Expand Up @@ -149,6 +167,20 @@ public void setTypeface(String fontFamilyName, int style, Typeface typeface) {
return Typeface.create(fontFamilyName, style);
}

private static
@Nullable Typeface createTypeface(
String fontPath,
String fontFamilyName,
int style) {
try {
return Typeface.createFromFile(fontPath);
} catch (RuntimeException e) {
// unfortunately Typeface.createFromFile throws an exception instead of returning null
// if the typeface doesn't exist
}
return Typeface.create(fontFamilyName, style);
}

private static class FontFamily {

private SparseArray<Typeface> mTypefaceSparseArray;
Expand Down
10 changes: 7 additions & 3 deletions ReactCommon/cxxreact/Instance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ void Instance::initializeBridge(
std::shared_ptr<ModuleRegistry> moduleRegistry) {
callback_ = std::move(callback);
moduleRegistry_ = std::move(moduleRegistry);

std::shared_ptr<ExecutorDelegate> delegate;
if (edf) {
delegate = edf->createExecutorDelegate(moduleRegistry_, callback_);
}

jsQueue->runOnQueueSync([this, delegate, &jsef, jsQueue]() mutable {
nativeToJsBridge_ = folly::make_unique<NativeToJsBridge>(
jsef.get(), delegate, moduleRegistry_, jsQueue, callback_);
jsef.get(), delegate, moduleRegistry_, jsQueue, callback_, jseConfigParams_);

std::lock_guard<std::mutex> lock(m_syncMutex);
m_syncReady = true;
Expand Down Expand Up @@ -183,7 +183,7 @@ void *Instance::getJavaScriptContext() {
bool Instance::isInspectable() {
return nativeToJsBridge_ ? nativeToJsBridge_->isInspectable() : false;
}

bool Instance::isBatchActive() {
return nativeToJsBridge_ ? nativeToJsBridge_->isBatchActive() : false;
}
Expand All @@ -201,6 +201,10 @@ void Instance::callJSCallback(uint64_t callbackId, folly::dynamic &&params) {
nativeToJsBridge_->invokeCallback((double)callbackId, std::move(params));
}

void Instance::setJSEConfigParams(std::shared_ptr<JSEConfigParams>&& jseConfigParams) {
jseConfigParams_ = std::move(jseConfigParams);
}

void Instance::registerBundle(uint32_t bundleId, const std::string& bundlePath) {
nativeToJsBridge_->registerBundle(bundleId, bundlePath);
}
Expand Down
2 changes: 2 additions & 0 deletions ReactCommon/cxxreact/Instance.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class RN_EXPORT Instance {
void callJSFunction(std::string &&module, std::string &&method,
folly::dynamic &&params);
void callJSCallback(uint64_t callbackId, folly::dynamic &&params);
virtual void setJSEConfigParams(std::shared_ptr<JSEConfigParams>&& jseConfigParams);

// This method is experimental, and may be modified or removed.
void registerBundle(uint32_t bundleId, const std::string& bundlePath);
Expand Down Expand Up @@ -117,6 +118,7 @@ class RN_EXPORT Instance {
std::shared_ptr<InstanceCallback> callback_;
std::unique_ptr<NativeToJsBridge> nativeToJsBridge_;
std::shared_ptr<ModuleRegistry> moduleRegistry_;
std::shared_ptr<JSEConfigParams> jseConfigParams_;

std::mutex m_syncMutex;
std::condition_variable m_syncCV;
Expand Down
12 changes: 6 additions & 6 deletions ReactCommon/cxxreact/NativeToJsBridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class JsToNativeBridge : public react::ExecutorDelegate {
std::shared_ptr<ModuleRegistry> getModuleRegistry() override {
return m_registry;
}

virtual bool isBatchActive() override {
return m_batchHadNativeModuleCalls;
}
Expand Down Expand Up @@ -88,12 +88,12 @@ NativeToJsBridge::NativeToJsBridge(
std::shared_ptr<ExecutorDelegate> delegate, // TODO(OSS Candidate ISS#2710739)
std::shared_ptr<ModuleRegistry> registry,
std::shared_ptr<MessageQueueThread> jsQueue,
std::shared_ptr<InstanceCallback> callback)
std::shared_ptr<InstanceCallback> callback,
std::shared_ptr<JSEConfigParams> jseConfigParams)
: m_destroyed(std::make_shared<bool>(false)),
m_delegate(delegate ? delegate : (std::make_shared<JsToNativeBridge>(registry, callback))),
m_executor(jsExecutorFactory->createJSExecutor(m_delegate, jsQueue)),
m_executorMessageQueueThread(std::move(jsQueue)),
m_inspectable(m_executor->isInspectable()) {}
m_executor(jsExecutorFactory->createJSExecutor(m_delegate, jsQueue, std::move(jseConfigParams))),
m_executorMessageQueueThread(std::move(jsQueue)) {}

// This must be called on the same thread on which the constructor was called.
NativeToJsBridge::~NativeToJsBridge() {
Expand Down Expand Up @@ -239,7 +239,7 @@ void* NativeToJsBridge::getJavaScriptContext() {
bool NativeToJsBridge::isInspectable() {
return m_inspectable;
}

bool NativeToJsBridge::isBatchActive() {
return m_delegate->isBatchActive();
}
Expand Down
3 changes: 2 additions & 1 deletion ReactCommon/cxxreact/NativeToJsBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class NativeToJsBridge {
std::shared_ptr<ExecutorDelegate> delegate, // TODO(OSS Candidate ISS#2710739)
std::shared_ptr<ModuleRegistry> registry,
std::shared_ptr<MessageQueueThread> jsQueue,
std::shared_ptr<InstanceCallback> callback);
std::shared_ptr<InstanceCallback> callback,
std::shared_ptr<JSEConfigParams> jseConfigParams);
virtual ~NativeToJsBridge();

/**
Expand Down