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

Commit aadd5a3

Browse files
authored
Add system font change listener for windows (#12276)
* Add windows font change logic * update * fix comment
1 parent eea7dd4 commit aadd5a3

File tree

17 files changed

+165
-2
lines changed

17 files changed

+165
-2
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,7 @@ FILE: ../../../flutter/third_party/txt/src/txt/platform_android.cc
10361036
FILE: ../../../flutter/third_party/txt/src/txt/platform_fuchsia.cc
10371037
FILE: ../../../flutter/third_party/txt/src/txt/platform_linux.cc
10381038
FILE: ../../../flutter/third_party/txt/src/txt/platform_mac.mm
1039+
FILE: ../../../flutter/third_party/txt/src/txt/platform_windows.cc
10391040
FILE: ../../../flutter/vulkan/vulkan_application.cc
10401041
FILE: ../../../flutter/vulkan/vulkan_application.h
10411042
FILE: ../../../flutter/vulkan/vulkan_backbuffer.cc

shell/common/shell.cc

Lines changed: 36 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,
@@ -1351,4 +1356,35 @@ fml::Status Shell::WaitForFirstFrame(fml::TimeDelta timeout) {
13511356
}
13521357
}
13531358

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

shell/common/shell.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,16 @@ 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
289+
/// FontCollection.
290+
/// It also clears the cached font families and send system
291+
/// channel message to framework to rebuild affected widgets.
292+
///
293+
/// @return Returns if shell reloads system fonts successfully.
294+
///
295+
bool ReloadSystemFonts();
296+
287297
//----------------------------------------------------------------------------
288298
/// @brief Used by embedders to get the last error from the Dart UI
289299
/// Isolate, if one exists.

shell/common/shell_test.cc

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

147+
std::shared_ptr<txt::FontCollection> ShellTest::GetFontCollection(
148+
Shell* shell) {
149+
return shell->weak_engine_->GetFontCollection().GetFontCollection();
150+
}
151+
147152
Settings ShellTest::CreateSettingsForFixture() {
148153
Settings settings;
149154
settings.leak_vm = false;

shell/common/shell_test.h

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

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

shell/common/shell_unittests.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,36 @@ 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+
if (font == nullptr) {
536+
// The system does not have default font. Aborts this test.
537+
return;
538+
}
539+
unsigned int id = font->getId();
540+
// The result should be cached.
541+
font = fontCollection->GetMinikinFontCollectionForFamilies(families, "en");
542+
ASSERT_EQ(font->getId(), id);
543+
bool result = shell->ReloadSystemFonts();
544+
545+
// The cache is cleared, and FontCollection will be assigned a new id.
546+
font = fontCollection->GetMinikinFontCollectionForFamilies(families, "en");
547+
ASSERT_NE(font->getId(), id);
548+
ASSERT_TRUE(result);
549+
shell.reset();
550+
}
551+
522552
TEST_F(ShellTest, WaitForFirstFrame) {
523553
auto settings = CreateSettingsForFixture();
524554
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);

0 commit comments

Comments
 (0)