7#include <QtCore/private/qnapi_p.h>
8#include <fontconfig/fontconfig.h>
9#include <qohosplugincore.h>
11using namespace std::string_literals;
16Q_GUI_EXPORT QFontDatabase::WritingSystem qt_writing_system_for_script(
int script);
20enum class JsSystemFontType {
27bool ohosNoUiChildMode =
false;
31 if (ohosNoUiChildMode)
34 auto fontModule = jsState.eval<QNapi::Object>(
"@ohos.font");
36 auto systemFontPaths = QNapi::getArrayElements<QStringList, QNapi::String>(
37 fontModule.call<QNapi::Array>(
"getSystemFontList"),
38 [&](QNapi::String fontName) {
39 auto fontInfo = fontModule.call(
"getFontByName", {fontName});
40 return fontInfo.IsObject()
41 ? QString::fromStdString(
42 QNapi::checkedCast<QNapi::Object>(fontInfo).get<QNapi::String>(
"path"))
46 systemFontPaths.removeAll(QString());
48 return systemFontPaths;
53 if (ohosNoUiChildMode)
56 auto uiFontDirs = QNapi::getArrayElements<QStringList, QNapi::String>(
57 jsState.eval<QNapi::Array>(
"@ohos.font.getUIFontConfig().fontDir"),
58 &QString::fromStdString);
60 QStringList nameFilters;
61 nameFilters << QLatin1String(
"*.ttf")
62 << QLatin1String(
"*.otf")
63 << QLatin1String(
"*.ttc");
66 for (
const auto &fontDir : uiFontDirs) {
67 for (
const QFileInfo &fileInfo : QDir(fontDir).entryInfoList(nameFilters, QDir::Files))
68 result.append(fileInfo.absoluteFilePath());
74QStringList getInstalledFontPaths()
76 if (ohosNoUiChildMode)
79 auto fontsPaths = QtOhos::evalInJsThreadWithPromise<std::vector<std::string>>(
80 [](QtOhos::JsState &jsState, QOhosTaskPromise<std::vector<std::string>> evalPromise) {
81 auto thenCatchPromises = std::move(evalPromise).makeThenCatchBranches(Q_FUNC_INFO);
82 jsState.evalToPromiseOrRejectOnThrow(
83 "@ohos.graphics.text.getSystemFontFullNamesByType(*)",
84 {
static_cast<
int>(JsSystemFontType::INSTALLED)})
86 [thenPromise = std::move(thenCatchPromises.first)](
const QtOhos::CallbackInfo &cbInfo)
mutable {
87 auto fontsNamesArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
89 if (fontsNamesArray.Length() == 0) {
94 auto fontsNames = QNapi::getArrayElements<std::vector<std::string>, QNapi::String>(fontsNamesArray);
95 auto sharedThenPromise = QtOhos::moveToSharedPtr(std::move(thenPromise).makeChained(Q_FUNC_INFO));
96 auto pathsCollector = std::make_shared<QOhosConsumer<std::string>>(
97 [sharedThenPromise, pushSize = fontsNames.size(), result = std::vector<std::string>()](
auto element)
mutable {
98 result.push_back(std::move(element));
99 if (result.size() == pushSize)
100 (*sharedThenPromise)(std::move(result));
103 for (
const auto &fontName : fontsNames) {
104 cbInfo.jsState().evalToPromiseOrRejectOnThrow(
105 "@ohos.graphics.text.getFontDescriptorByFullName(*)",
106 {fontName,
static_cast<
int>(JsSystemFontType::INSTALLED)})
108 [pathsCollector](
const QtOhos::CallbackInfo &cbInfo) {
109 auto fontDescriptor = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
110 auto optFontPath = QNapi::getOptionalPropOrEmpty<QNapi::String>(fontDescriptor,
"path");
111 (*pathsCollector)(!optFontPath.IsEmpty() ? optFontPath.Utf8Value() :
""s);
114 [pathsCollector, fontName](
const QtOhos::CallbackInfo &cbInfo) {
115 QtOhos::logJsCallbackError(
116 cbInfo, (
"getFontDescriptorByFullName("s + fontName +
") failed"s).c_str());
117 (*pathsCollector)(
""s);
122 [catchPromise = std::move(thenCatchPromises.second)](
const QtOhos::CallbackInfo &cbInfo) {
123 QtOhos::logJsCallbackError(cbInfo,
"getSystemFontFullNamesByType() failed");
131 fontsPaths.begin(), fontsPaths.end(),
132 std::back_inserter(result), QString::fromStdString);
133 result.removeAll(QString());
141 if (ohosNoUiChildMode)
144 std::string defaultFontFamily;
145 auto genericFonts = jsState.eval<QNapi::Array>(
"@ohos.font.getUIFontConfig().generic");
146 if (genericFonts.Length() > 0) {
147 auto firstFont = QNapi::checkedCast<QNapi::Object>(genericFonts.Get(0U));
148 defaultFontFamily = firstFont.get<QNapi::String>(
"family");
150 qFatal(
"Failed to get system default font family name."
151 " The reason is: empty `@ohos.font.getUIFontConfig().generic` array.");
154 return defaultFontFamily;
157void registerSystemFonts()
159 QStringList fontPaths;
162 fontPaths.append(getSystemFontPaths(jsState));
163 fontPaths.append(getUIFontPaths(jsState));
166 fontPaths.append(getInstalledFontPaths());
167 fontPaths.removeDuplicates();
169 QSet<QString> uniqueFontDirs;
170 for (
const QString &fontPath : fontPaths)
171 uniqueFontDirs.insert(QFileInfo(fontPath).absolutePath());
173 FcConfig *config = FcConfigGetCurrent();
174 if (config !=
nullptr) {
175 for (
const QString &dir : uniqueFontDirs)
176 FcConfigAppFontAddDir(config,
reinterpret_cast<
const FcChar8 *>(dir.toUtf8().constData()));
177 FcConfigBuildFonts(config);
179 qOhosPrintfError(
"Failed to get fontconfig current configuration.");
188 ohosNoUiChildMode =
true;
195 registerSystemFonts();
197 QFontconfigDatabase::populateFontDatabase();
202 QFont::StyleHint styleHint,
203 QFontDatabasePrivate::ExtendedScript script)
const
207 const QFontDatabase::WritingSystem ws = qt_writing_system_for_script(script);
208 const bool defaultFontSupportsScript =
209 ws == QFontDatabase::Any ||
210 QFontDatabase::writingSystems(defaultFont().family()).contains(ws);
212 if (defaultFontSupportsScript)
213 result.append(defaultFont().family());
215 if (styleHint == QFont::Monospace || styleHint == QFont::Courier)
216 result.append(QString::fromUtf8(qgetenv(
"Droid Sans Mono;Droid Sans;Noto Sans")).split(QLatin1Char(
';')));
217 else if (styleHint == QFont::Serif)
218 result.append(QString::fromUtf8(qgetenv(
"Noto Serif")).split(QLatin1Char(
';')));
220 result.append(QString::fromUtf8(qgetenv(
"Roboto;Droid Sans")).split(QLatin1Char(
';')));
221 result.append(QFontconfigDatabase::fallbacksForFamily(family, style, styleHint, script));
228 static const char *
const preferredDefaultFontFamily =
"HarmonyOS Sans SC";
229 static const QString defaultFontFamily =
230 QFontDatabase::families().contains(QLatin1String(preferredDefaultFontFamily))
231 ? QString::fromStdString(preferredDefaultFontFamily)
232 : QtOhos::evalInJsThread(
234 return QString::fromStdString(getDefaultFontFamily(jsState));
237 return QFont(defaultFontFamily);
void runInJsThreadAndWait(const std::function< void(JsState &)> &task, std::string callerContextName={})
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)