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

Commit ece29f4

Browse files
committed
Add windows font change logic
1 parent e7fd442 commit ece29f4

16 files changed

+159
-2
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,
@@ -1351,4 +1356,36 @@ 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,
1384+
std::vector<uint8_t>(message.begin(), message.end()),
1385+
nullptr);
1386+
1387+
OnPlatformViewDispatchPlatformMessage(fontsChangeMessage);
1388+
return true;
1389+
}
1390+
13541391
} // 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
@@ -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: 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)