Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7c47a64

Browse files
committed
Add windows font change logic
1 parent f15cc34 commit 7c47a64

16 files changed

+159
-3
lines changed

shell/common/shell.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,18 @@
2626
#include "flutter/shell/common/skia_event_tracer_impl.h"
2727
#include "flutter/shell/common/switches.h"
2828
#include "flutter/shell/common/vsync_waiter.h"
29+
#include "rapidjson/stringbuffer.h"
30+
#include "rapidjson/writer.h"
2931
#include "third_party/dart/runtime/include/dart_tools_api.h"
3032
#include "third_party/skia/include/core/SkGraphics.h"
3133
#include "third_party/tonic/common/log.h"
3234

3335
namespace flutter {
3436

3537
constexpr char kSkiaChannel[] = "flutter/skia";
38+
constexpr char kSystemChannel[] = "flutter/system";
39+
constexpr char kTypeKey[] = "type";
40+
constexpr char kFontChange[] = "fontsChange";
3641

3742
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
3843
DartVMRef vm,
@@ -1357,4 +1362,36 @@ fml::Status Shell::WaitForFirstFrame(fml::TimeDelta timeout) {
13571362
}
13581363
}
13591364

1365+
bool Shell::ReloadSystemFonts() {
1366+
FML_DCHECK(is_setup_);
1367+
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
1368+
1369+
if (!engine_) {
1370+
return false;
1371+
}
1372+
engine_->GetFontCollection().GetFontCollection()->SetupDefaultFontManager();
1373+
engine_->GetFontCollection().GetFontCollection()->ClearFontFamilyCache();
1374+
// After system fonts are reloaded, we send a system channel message
1375+
// to notify flutter framework.
1376+
rapidjson::Document document;
1377+
document.SetObject();
1378+
auto& allocator = document.GetAllocator();
1379+
rapidjson::Value message_value;
1380+
message_value.SetString(kFontChange, allocator);
1381+
document.AddMember(kTypeKey, message_value, allocator);
1382+
1383+
rapidjson::StringBuffer buffer;
1384+
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
1385+
document.Accept(writer);
1386+
std::string message(buffer.GetString(), buffer.GetSize());
1387+
fml::RefPtr<PlatformMessage> fontsChangeMessage =
1388+
fml::MakeRefCounted<flutter::PlatformMessage>(
1389+
kSystemChannel,
1390+
std::vector<uint8_t>(message.begin(), message.end()),
1391+
nullptr);
1392+
1393+
OnPlatformViewDispatchPlatformMessage(fontsChangeMessage);
1394+
return true;
1395+
}
1396+
13601397
} // namespace flutter

shell/common/shell.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,15 @@ class Shell final : public PlatformView::Delegate,
284284
///
285285
fml::Status WaitForFirstFrame(fml::TimeDelta timeout);
286286

287+
//----------------------------------------------------------------------------
288+
/// @brief Used by embedders to reload the system fonts in FontCollection.
289+
/// It also clears the cached font families and send system channel
290+
/// message to framework to rebuild affected widgets.
291+
///
292+
/// @return Returns if shell reloads system fonts successfully.
293+
///
294+
bool ReloadSystemFonts();
295+
287296
//----------------------------------------------------------------------------
288297
/// @brief Used by embedders to get the last error from the Dart UI
289298
/// Isolate, if one exists.

shell/common/shell_test.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ bool ShellTest::GetNeedsReportTimings(Shell* shell) {
166166
return shell->needs_report_timings_;
167167
}
168168

169+
std::shared_ptr<txt::FontCollection> ShellTest::GetFontCollection(
170+
Shell* shell) {
171+
return shell->weak_engine_->GetFontCollection().GetFontCollection();
172+
}
173+
169174
Settings ShellTest::CreateSettingsForFixture() {
170175
Settings settings;
171176
settings.leak_vm = false;

shell/common/shell_test.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class ShellTest : public ThreadTest {
5353
static bool GetNeedsReportTimings(Shell* shell);
5454
static void SetNeedsReportTimings(Shell* shell, bool value);
5555

56+
std::shared_ptr<txt::FontCollection> GetFontCollection(Shell* shell);
57+
5658
// Do not assert |UnreportedTimingsCount| to be positive in any tests.
5759
// Otherwise those tests will be flaky as the clearing of unreported timings
5860
// is unpredictive.

shell/common/shell_unittests.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,32 @@ TEST_F(ShellTest, ReportTimingsIsCalledImmediatelyAfterTheFirstFrame) {
519519
ASSERT_EQ(timestamps.size(), FrameTiming::kCount);
520520
}
521521

522+
TEST_F(ShellTest, ReloadSystemFonts) {
523+
auto settings = CreateSettingsForFixture();
524+
525+
fml::MessageLoop::EnsureInitializedForCurrentThread();
526+
auto task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
527+
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
528+
task_runner);
529+
auto shell = CreateShell(std::move(settings), std::move(task_runners));
530+
531+
auto fontCollection = GetFontCollection(shell.get());
532+
std::vector<std::string> families(1, "Robotofake");
533+
auto font =
534+
fontCollection->GetMinikinFontCollectionForFamilies(families, "en");
535+
ASSERT_EQ(font->getId(), static_cast<double>(0));
536+
// Result should be cached.
537+
font = fontCollection->GetMinikinFontCollectionForFamilies(families, "en");
538+
ASSERT_EQ(font->getId(), static_cast<double>(0));
539+
bool result = shell->ReloadSystemFonts();
540+
541+
// Cache is cleared, and FontCollection will be assigned a new id in
542+
// incremental order.
543+
font = fontCollection->GetMinikinFontCollectionForFamilies(families, "en");
544+
ASSERT_EQ(font->getId(), static_cast<double>(1));
545+
ASSERT_TRUE(result);
546+
}
547+
522548
TEST_F(ShellTest, WaitForFirstFrame) {
523549
auto settings = CreateSettingsForFixture();
524550
std::unique_ptr<Shell> shell = CreateShell(settings);

shell/platform/embedder/embedder.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,22 @@ FlutterEngineResult FlutterEngineOnVsync(FLUTTER_API_SYMBOL(FlutterEngine)
12791279
return kSuccess;
12801280
}
12811281

1282+
FlutterEngineResult FlutterEngineReloadSystemFonts(
1283+
FLUTTER_API_SYMBOL(FlutterEngine) engine) {
1284+
if (engine == nullptr) {
1285+
return LOG_EMBEDDER_ERROR(kInvalidArguments);
1286+
}
1287+
1288+
TRACE_EVENT0("flutter", "FlutterEngineReloadSystemFonts");
1289+
1290+
if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
1291+
->ReloadSystemFonts()) {
1292+
return LOG_EMBEDDER_ERROR(kInternalInconsistency);
1293+
}
1294+
1295+
return kSuccess;
1296+
}
1297+
12821298
void FlutterEngineTraceEventDurationBegin(const char* name) {
12831299
fml::tracing::TraceEvent0("flutter", name);
12841300
}

shell/platform/embedder/embedder.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,17 @@ FlutterEngineResult FlutterEngineOnVsync(FLUTTER_API_SYMBOL(FlutterEngine)
12001200
uint64_t frame_start_time_nanos,
12011201
uint64_t frame_target_time_nanos);
12021202

1203+
//------------------------------------------------------------------------------
1204+
/// @brief Reloads the system fonts in engine.
1205+
///
1206+
/// @param[in] engine. A running engine instance.
1207+
///
1208+
/// @return The result of the call.
1209+
///
1210+
FLUTTER_EXPORT
1211+
FlutterEngineResult FlutterEngineReloadSystemFonts(
1212+
FLUTTER_API_SYMBOL(FlutterEngine) engine);
1213+
12031214
//------------------------------------------------------------------------------
12041215
/// @brief A profiling utility. Logs a trace duration begin event to the
12051216
/// timeline. If the timeline is unavailable or disabled, this has

shell/platform/embedder/embedder_engine.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ bool EmbedderEngine::OnVsyncEvent(intptr_t baton,
186186
frame_target_time);
187187
}
188188

189+
bool EmbedderEngine::ReloadSystemFonts() {
190+
return shell_->ReloadSystemFonts();
191+
}
192+
189193
bool EmbedderEngine::PostRenderThreadTask(fml::closure task) {
190194
if (!IsValid()) {
191195
return false;

shell/platform/embedder/embedder_engine.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class EmbedderEngine {
6767
fml::TimePoint frame_start_time,
6868
fml::TimePoint frame_target_time);
6969

70+
bool ReloadSystemFonts();
71+
7072
bool PostRenderThreadTask(fml::closure task);
7173

7274
bool RunTask(const FlutterTask* task);

shell/platform/embedder/tests/embedder_unittests.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,16 @@ TEST(EmbedderTestNoFixture, CanGetCurrentTimeInNanoseconds) {
235235
ASSERT_LT((point2 - point1), fml::TimeDelta::FromMilliseconds(1));
236236
}
237237

238+
TEST_F(EmbedderTest, CanReloadSystemFonts) {
239+
auto& context = GetEmbedderContext();
240+
EmbedderConfigBuilder builder(context);
241+
auto engine = builder.LaunchEngine();
242+
ASSERT_TRUE(engine.is_valid());
243+
244+
auto result = FlutterEngineReloadSystemFonts(engine.get());
245+
ASSERT_EQ(result, kSuccess);
246+
}
247+
238248
TEST_F(EmbedderTest, CanCreateOpenGLRenderingEngine) {
239249
EmbedderConfigBuilder builder(GetEmbedderContext());
240250
builder.SetOpenGLRendererConfig(SkISize::Make(1, 1));

0 commit comments

Comments
 (0)