mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add system font change listener for windows (flutter/engine#12276)
* Add windows font change logic * update * fix comment
This commit is contained in:
parent
f51af4acdd
commit
051ed653cc
@ -1036,6 +1036,7 @@ FILE: ../../../flutter/third_party/txt/src/txt/platform_android.cc
|
||||
FILE: ../../../flutter/third_party/txt/src/txt/platform_fuchsia.cc
|
||||
FILE: ../../../flutter/third_party/txt/src/txt/platform_linux.cc
|
||||
FILE: ../../../flutter/third_party/txt/src/txt/platform_mac.mm
|
||||
FILE: ../../../flutter/third_party/txt/src/txt/platform_windows.cc
|
||||
FILE: ../../../flutter/vulkan/vulkan_application.cc
|
||||
FILE: ../../../flutter/vulkan/vulkan_application.h
|
||||
FILE: ../../../flutter/vulkan/vulkan_backbuffer.cc
|
||||
|
||||
@ -26,6 +26,8 @@
|
||||
#include "flutter/shell/common/skia_event_tracer_impl.h"
|
||||
#include "flutter/shell/common/switches.h"
|
||||
#include "flutter/shell/common/vsync_waiter.h"
|
||||
#include "rapidjson/stringbuffer.h"
|
||||
#include "rapidjson/writer.h"
|
||||
#include "third_party/dart/runtime/include/dart_tools_api.h"
|
||||
#include "third_party/skia/include/core/SkGraphics.h"
|
||||
#include "third_party/tonic/common/log.h"
|
||||
@ -33,6 +35,9 @@
|
||||
namespace flutter {
|
||||
|
||||
constexpr char kSkiaChannel[] = "flutter/skia";
|
||||
constexpr char kSystemChannel[] = "flutter/system";
|
||||
constexpr char kTypeKey[] = "type";
|
||||
constexpr char kFontChange[] = "fontsChange";
|
||||
|
||||
std::unique_ptr<Shell> Shell::CreateShellOnPlatformThread(
|
||||
DartVMRef vm,
|
||||
@ -1351,4 +1356,35 @@ fml::Status Shell::WaitForFirstFrame(fml::TimeDelta timeout) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Shell::ReloadSystemFonts() {
|
||||
FML_DCHECK(is_setup_);
|
||||
FML_DCHECK(task_runners_.GetPlatformTaskRunner()->RunsTasksOnCurrentThread());
|
||||
|
||||
if (!engine_) {
|
||||
return false;
|
||||
}
|
||||
engine_->GetFontCollection().GetFontCollection()->SetupDefaultFontManager();
|
||||
engine_->GetFontCollection().GetFontCollection()->ClearFontFamilyCache();
|
||||
// After system fonts are reloaded, we send a system channel message
|
||||
// to notify flutter framework.
|
||||
rapidjson::Document document;
|
||||
document.SetObject();
|
||||
auto& allocator = document.GetAllocator();
|
||||
rapidjson::Value message_value;
|
||||
message_value.SetString(kFontChange, allocator);
|
||||
document.AddMember(kTypeKey, message_value, allocator);
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
document.Accept(writer);
|
||||
std::string message = buffer.GetString();
|
||||
fml::RefPtr<PlatformMessage> fontsChangeMessage =
|
||||
fml::MakeRefCounted<flutter::PlatformMessage>(
|
||||
kSystemChannel, std::vector<uint8_t>(message.begin(), message.end()),
|
||||
nullptr);
|
||||
|
||||
OnPlatformViewDispatchPlatformMessage(fontsChangeMessage);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -284,6 +284,16 @@ class Shell final : public PlatformView::Delegate,
|
||||
///
|
||||
fml::Status WaitForFirstFrame(fml::TimeDelta timeout);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Used by embedders to reload the system fonts in
|
||||
/// FontCollection.
|
||||
/// It also clears the cached font families and send system
|
||||
/// channel message to framework to rebuild affected widgets.
|
||||
///
|
||||
/// @return Returns if shell reloads system fonts successfully.
|
||||
///
|
||||
bool ReloadSystemFonts();
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
/// @brief Used by embedders to get the last error from the Dart UI
|
||||
/// Isolate, if one exists.
|
||||
|
||||
@ -144,6 +144,11 @@ bool ShellTest::GetNeedsReportTimings(Shell* shell) {
|
||||
return shell->needs_report_timings_;
|
||||
}
|
||||
|
||||
std::shared_ptr<txt::FontCollection> ShellTest::GetFontCollection(
|
||||
Shell* shell) {
|
||||
return shell->weak_engine_->GetFontCollection().GetFontCollection();
|
||||
}
|
||||
|
||||
Settings ShellTest::CreateSettingsForFixture() {
|
||||
Settings settings;
|
||||
settings.leak_vm = false;
|
||||
|
||||
@ -51,6 +51,8 @@ class ShellTest : public ThreadTest {
|
||||
static bool GetNeedsReportTimings(Shell* shell);
|
||||
static void SetNeedsReportTimings(Shell* shell, bool value);
|
||||
|
||||
std::shared_ptr<txt::FontCollection> GetFontCollection(Shell* shell);
|
||||
|
||||
// Do not assert |UnreportedTimingsCount| to be positive in any tests.
|
||||
// Otherwise those tests will be flaky as the clearing of unreported timings
|
||||
// is unpredictive.
|
||||
|
||||
@ -519,6 +519,36 @@ TEST_F(ShellTest, ReportTimingsIsCalledImmediatelyAfterTheFirstFrame) {
|
||||
ASSERT_EQ(timestamps.size(), FrameTiming::kCount);
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, ReloadSystemFonts) {
|
||||
auto settings = CreateSettingsForFixture();
|
||||
|
||||
fml::MessageLoop::EnsureInitializedForCurrentThread();
|
||||
auto task_runner = fml::MessageLoop::GetCurrent().GetTaskRunner();
|
||||
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
|
||||
task_runner);
|
||||
auto shell = CreateShell(std::move(settings), std::move(task_runners));
|
||||
|
||||
auto fontCollection = GetFontCollection(shell.get());
|
||||
std::vector<std::string> families(1, "Robotofake");
|
||||
auto font =
|
||||
fontCollection->GetMinikinFontCollectionForFamilies(families, "en");
|
||||
if (font == nullptr) {
|
||||
// The system does not have default font. Aborts this test.
|
||||
return;
|
||||
}
|
||||
unsigned int id = font->getId();
|
||||
// The result should be cached.
|
||||
font = fontCollection->GetMinikinFontCollectionForFamilies(families, "en");
|
||||
ASSERT_EQ(font->getId(), id);
|
||||
bool result = shell->ReloadSystemFonts();
|
||||
|
||||
// The cache is cleared, and FontCollection will be assigned a new id.
|
||||
font = fontCollection->GetMinikinFontCollectionForFamilies(families, "en");
|
||||
ASSERT_NE(font->getId(), id);
|
||||
ASSERT_TRUE(result);
|
||||
shell.reset();
|
||||
}
|
||||
|
||||
TEST_F(ShellTest, WaitForFirstFrame) {
|
||||
auto settings = CreateSettingsForFixture();
|
||||
std::unique_ptr<Shell> shell = CreateShell(settings);
|
||||
|
||||
@ -1279,6 +1279,22 @@ FlutterEngineResult FlutterEngineOnVsync(FLUTTER_API_SYMBOL(FlutterEngine)
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
FlutterEngineResult FlutterEngineReloadSystemFonts(
|
||||
FLUTTER_API_SYMBOL(FlutterEngine) engine) {
|
||||
if (engine == nullptr) {
|
||||
return LOG_EMBEDDER_ERROR(kInvalidArguments);
|
||||
}
|
||||
|
||||
TRACE_EVENT0("flutter", "FlutterEngineReloadSystemFonts");
|
||||
|
||||
if (!reinterpret_cast<flutter::EmbedderEngine*>(engine)
|
||||
->ReloadSystemFonts()) {
|
||||
return LOG_EMBEDDER_ERROR(kInternalInconsistency);
|
||||
}
|
||||
|
||||
return kSuccess;
|
||||
}
|
||||
|
||||
void FlutterEngineTraceEventDurationBegin(const char* name) {
|
||||
fml::tracing::TraceEvent0("flutter", name);
|
||||
}
|
||||
|
||||
@ -1200,6 +1200,17 @@ FlutterEngineResult FlutterEngineOnVsync(FLUTTER_API_SYMBOL(FlutterEngine)
|
||||
uint64_t frame_start_time_nanos,
|
||||
uint64_t frame_target_time_nanos);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @brief Reloads the system fonts in engine.
|
||||
///
|
||||
/// @param[in] engine. A running engine instance.
|
||||
///
|
||||
/// @return The result of the call.
|
||||
///
|
||||
FLUTTER_EXPORT
|
||||
FlutterEngineResult FlutterEngineReloadSystemFonts(
|
||||
FLUTTER_API_SYMBOL(FlutterEngine) engine);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @brief A profiling utility. Logs a trace duration begin event to the
|
||||
/// timeline. If the timeline is unavailable or disabled, this has
|
||||
|
||||
@ -186,6 +186,10 @@ bool EmbedderEngine::OnVsyncEvent(intptr_t baton,
|
||||
frame_target_time);
|
||||
}
|
||||
|
||||
bool EmbedderEngine::ReloadSystemFonts() {
|
||||
return shell_->ReloadSystemFonts();
|
||||
}
|
||||
|
||||
bool EmbedderEngine::PostRenderThreadTask(fml::closure task) {
|
||||
if (!IsValid()) {
|
||||
return false;
|
||||
|
||||
@ -67,6 +67,8 @@ class EmbedderEngine {
|
||||
fml::TimePoint frame_start_time,
|
||||
fml::TimePoint frame_target_time);
|
||||
|
||||
bool ReloadSystemFonts();
|
||||
|
||||
bool PostRenderThreadTask(fml::closure task);
|
||||
|
||||
bool RunTask(const FlutterTask* task);
|
||||
|
||||
@ -235,6 +235,17 @@ TEST(EmbedderTestNoFixture, CanGetCurrentTimeInNanoseconds) {
|
||||
ASSERT_LT((point2 - point1), fml::TimeDelta::FromMilliseconds(1));
|
||||
}
|
||||
|
||||
TEST_F(EmbedderTest, CanReloadSystemFonts) {
|
||||
auto& context = GetEmbedderContext();
|
||||
EmbedderConfigBuilder builder(context);
|
||||
builder.SetSoftwareRendererConfig();
|
||||
auto engine = builder.LaunchEngine();
|
||||
ASSERT_TRUE(engine.is_valid());
|
||||
|
||||
auto result = FlutterEngineReloadSystemFonts(engine.get());
|
||||
ASSERT_EQ(result, kSuccess);
|
||||
}
|
||||
|
||||
TEST_F(EmbedderTest, CanCreateOpenGLRenderingEngine) {
|
||||
EmbedderConfigBuilder builder(GetEmbedderContext());
|
||||
builder.SetOpenGLRendererConfig(SkISize::Make(1, 1));
|
||||
|
||||
@ -147,6 +147,13 @@ void Win32FlutterWindow::OnClose() {
|
||||
messageloop_running_ = false;
|
||||
}
|
||||
|
||||
void Win32FlutterWindow::OnFontChange() {
|
||||
if (engine_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
FlutterEngineReloadSystemFonts(engine_);
|
||||
}
|
||||
|
||||
// Sends new size information to FlutterEngine.
|
||||
void Win32FlutterWindow::SendWindowMetrics() {
|
||||
if (engine_ == nullptr) {
|
||||
|
||||
@ -65,6 +65,9 @@ class Win32FlutterWindow : public Win32Window {
|
||||
// |Win32Window|
|
||||
void OnClose();
|
||||
|
||||
// |Win32Window|
|
||||
void OnFontChange() override;
|
||||
|
||||
// Configures the window instance with an instance of a running Flutter engine
|
||||
// returning a configured FlutterDesktopWindowControllerRef.
|
||||
void SetState(FLUTTER_API_SYMBOL(FlutterEngine) state);
|
||||
|
||||
@ -129,7 +129,9 @@ Win32Window::MessageHandler(HWND hwnd,
|
||||
current_height_ = height;
|
||||
window->HandleResize(width, height);
|
||||
break;
|
||||
|
||||
case WM_FONTCHANGE:
|
||||
window->OnFontChange();
|
||||
break;
|
||||
case WM_MOUSEMOVE:
|
||||
xPos = GET_X_LPARAM(lparam);
|
||||
yPos = GET_Y_LPARAM(lparam);
|
||||
|
||||
@ -97,9 +97,12 @@ class Win32Window {
|
||||
// Called when mouse scrollwheel input occurs.
|
||||
virtual void OnScroll(double delta_x, double delta_y) = 0;
|
||||
|
||||
// Called when the user closes the Windows
|
||||
// Called when the user closes the Windows.
|
||||
virtual void OnClose() = 0;
|
||||
|
||||
// Called when the system font change.
|
||||
virtual void OnFontChange() = 0;
|
||||
|
||||
UINT GetCurrentDPI();
|
||||
|
||||
UINT GetCurrentWidth();
|
||||
|
||||
2
engine/src/flutter/third_party/txt/BUILD.gn
vendored
2
engine/src/flutter/third_party/txt/BUILD.gn
vendored
@ -160,6 +160,8 @@ source_set("txt") {
|
||||
sources += [ "src/txt/platform_linux.cc" ]
|
||||
} else if (is_fuchsia) {
|
||||
sources += [ "src/txt/platform_fuchsia.cc" ]
|
||||
} else if (is_win) {
|
||||
sources += [ "src/txt/platform_windows.cc" ]
|
||||
} else {
|
||||
sources += [ "src/txt/platform.cc" ]
|
||||
}
|
||||
|
||||
18
engine/src/flutter/third_party/txt/src/txt/platform_windows.cc
vendored
Normal file
18
engine/src/flutter/third_party/txt/src/txt/platform_windows.cc
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "third_party/skia/include/ports/SkTypeface_win.h"
|
||||
#include "txt/platform.h"
|
||||
|
||||
namespace txt {
|
||||
|
||||
std::string GetDefaultFontFamily() {
|
||||
return "Arial";
|
||||
}
|
||||
|
||||
sk_sp<SkFontMgr> GetDefaultFontManager() {
|
||||
return SkFontMgr_New_DirectWrite();
|
||||
}
|
||||
|
||||
} // namespace txt
|
||||
Loading…
x
Reference in New Issue
Block a user