wasm: add local font loading manual test

This tests allows configuring font loading options from
the test web page.

Change-Id: I15d850addb38329423722d1763ace8836dca2484
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Reviewed-by: Lorn Potter <lorn.potter@gmail.com>
This commit is contained in:
Morten Sørvig 2023-12-14 15:13:11 +01:00
parent bb68cc5844
commit 83bfd368b3
5 changed files with 270 additions and 0 deletions

View File

@ -7,6 +7,7 @@ add_subdirectory(a11y)
if(QT_FEATURE_widgets)
add_subdirectory(cursors)
add_subdirectory(localfiles)
add_subdirectory(localfonts)
add_subdirectory(qstdweb)
add_subdirectory(clipboard)
endif()

View File

@ -0,0 +1,4 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(fontloading)

View File

@ -0,0 +1,20 @@
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
qt_internal_add_manual_test(fontloading
GUI
SOURCES
main.cpp
LIBRARIES
Qt::Core
Qt::Gui
Qt::Widgets
)
add_custom_command(
TARGET fontloading POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/fontloading.html
${CMAKE_CURRENT_BINARY_DIR}/fontloading.html)
#add_custom_target(html DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fontloading.html)
#add_dependencies(fontloading html)

View File

@ -0,0 +1,167 @@
<!doctype html>
<script src="qtloader.js"></script>
<script src="fontloading.js"></script>
<style>
body {
padding: 5px;
}
.container {
display: flex;
}
.column {
flex: 1;
}
</style>
<script>
// UI
let familyCount;
let families;
// Data
let fontFamilies = new Set();
let loadStartTime;
// App
let instance;
async function updatePermissionStatus() {
let permissonStatusElement = document.getElementById("permissonStatus");
let permissionStatus = await navigator.permissions.query({ name: "local-fonts" })
permissonStatusElement.innerHTML = permissionStatus.state;
}
window.onload = async () => {
let supported = document.getElementById("supported");
let permissonStatus = document.getElementById("permissonStatus");
let permission = document.getElementById("permission");
let defaultfonts = document.getElementById("defaultfonts");
let allfonts = document.getElementById("allfonts");
let start = document.getElementById("start");
let loadFonts = document.getElementById("loadFonts");
startupTime = document.getElementById("startupTime");
familyCount = document.getElementById("familyCount");
families = document.getElementById("families");
fontFamilies.clear();
let localFontsAccessSupported = window.queryLocalFonts ? true : false
if (localFontsAccessSupported) {
supported.innerHTML = "True"
} else {
supported.innerHTML = "False"
return;
}
updatePermissionStatus();
const module = WebAssembly.compileStreaming(fetch('fontloading.wasm'));
start.onclick = async () => {
// Delete any previous instance.
if (instance) {
instance.deleteapp(); // see main.cpp
instance = null;
}
loadStartTime = performance.now();
startupTime.innerHTML = 0;
familyCount.innerHTML = 0;
let localFontFamilyLoadCollection = "NoFontFamilies"
if (defaultfonts.checked)
localFontFamilyLoadCollection = "DefaultFontFamilies"
else if (allfonts.checked)
localFontFamilyLoadCollection = "AllFontFamilies"
let qtcontainer = document.getElementById("qtcontainer");
qtcontainer.innerHTML = ""; // clear children
qtcontainer.style.visibility = "hidden";
let extraFonts = document.getElementById("extrafonts").value.split(",");
let config = {
qt: {
module: module,
containerElements: [qtcontainer],
onLoaded: () => {
console.log("JS: onLoaded")
qtcontainer.style.visibility = "visible";
},
entryFunction: window.fontloading_entry,
localFonts: {
requestPermission: permission.checked,
familiesCollection: localFontFamilyLoadCollection,
extraFamilies: extraFonts,
}
}
}
instance = await qtLoad(config);
updatePermissionStatus();
}
loadFonts.onclick = async () => {
loadStartTime = null; // disable timer
let fontsFamilies = document.getElementById("extraRuntimeFontFamilies").value.split(",");
console.log("extraRuntimeFontFamilies: " + fontsFamilies);
instance.qtLoadLocalFontFamilies(fontsFamilies);
}
};
function fontFamiliesLoaded(count) {
familyCount.innerHTML = count;
if (loadStartTime) {
elapsed = performance.now() - loadStartTime;
startupTime.innerHTML = Math.round(elapsed + 1);
}
}
function fontFamilyLoaded(family) {
fontFamilies.add(family);
}
</script>
<h2>Local Font Loading Test</h2>
<p>Click "Load" button below to load the Qt test app with the specified settings. This test provides additional logs on the JavaScript console.</p>
<div class="container">
<div class="column">
<span>Browser supports the Local Font Access API: </span><span id="supported" style="font-weight: bold;"></span><br>
<span>Local Font Access permission status: </span><span id="permissonStatus" style="font-weight: bold;"></span><br>
<br>
<input type="checkbox" id="permission"><label for="permission">Ask for Local Font access permission on startup</label><br>
<input type="radio" id="nofonts" name="fontset"></input><label for="nofonts">No local fonts</label><br>
<input type="radio" id="defaultfonts" name="fontset" checked></input><label for="defaultfonts">Default local fonts (web-safe fonts)</label><br>
<input type="radio" id="allfonts" name="fontset"></input><label for="allfonts">All local fonts (warning: extremely slow)</label><br>
<br>
<label for="extrafonts">Extra Font Families (comma separated) </label><input type="text" id="extrafonts" value=""></input><br>
<br>
<input type="checkbox" id="permission"><label for="permission">Enable 'Fonts' Logging Category</label><br>
<input type="checkbox" id="permission"><label for="permission">Enable Font Streaming</label><br>
<br>
<button type="button" id="start">Start Application</button><br>
<br>
<span>Startup time: </span><span id="startupTime"></span><br>
<span>Font family count: </span><span id="familyCount"></span><br>
<span>Font families: </span><span id="families"></span><br>
<br>
<button type="button" id="loadFonts">Load Extra Fonts</button>
<input type="text" id="extraRuntimeFontFamilies" value=""></input><br>
</div>
<div class="column">
<div id="qtcontainer" style="width: 100%; height: 300px; visibility: hidden;"></div>
</div>
</div>

View File

@ -0,0 +1,78 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QtGui>
#include <QtWidgets>
#include <emscripten/bind.h>
#include <emscripten/val.h>
using namespace emscripten;
class FontViewer : public QWidget
{
public:
FontViewer() {
QTextEdit *edit = new QTextEdit;
edit->setPlainText("The quick brown fox jumps over the lazy dog\nHow quickly daft jumping zebras vex\nPack my box with five dozen liquor jugs");
QComboBox *combo = new QComboBox;
combo->addItems(QFontDatabase::families());
connect(combo, &QComboBox::currentTextChanged, [=](const QString &family) {
QFont font(family);
edit->setFont(font);
});
QObject::connect(qApp, &QGuiApplication::fontDatabaseChanged, [=]() {
QStringList families = QFontDatabase::families();
combo->clear();
combo->addItems(families);
});
QLayout *layout = new QVBoxLayout;
layout->addWidget(edit);
layout->addWidget(combo);
setLayout(layout);
}
};
FontViewer *g_viewer = nullptr;
QApplication *g_app = nullptr;
void deleteapp() {
delete g_viewer;
delete g_app;
};
EMSCRIPTEN_BINDINGS(fonloading) {
function("deleteapp", &deleteapp);
}
int main(int argc, char **argv)
{
qDebug() << "C++ main: Creating application";
g_app = new QApplication(argc, argv);
// Make sure there is one call to fontFamiliesLoaded at startup,
// even if no further fonts are loaded.
QTimer::singleShot(0, [=]() {
emscripten::val window = emscripten::val::global("window");
window.call<void>("fontFamiliesLoaded", QFontDatabase::families().count());
});
g_viewer = new FontViewer();
g_viewer->show();
QObject::connect(g_app, &QGuiApplication::fontDatabaseChanged, [=]() {
QStringList families = QFontDatabase::families();
emscripten::val window = emscripten::val::global("window");
window.call<void>("fontFamiliesLoaded", families.count());
for (int i = 0; i < families.count(); ++i) {
window.call<void>("fontFamilyLoaded", families[i].toStdString());
}
});
}