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::evalInJsThreadWithConsumer<std::vector<std::string>>(
80 [](QtOhos::JsState &jsState, QOhosConsumer<std::vector<std::string>> resultConsumer) {
81 jsState.eval<QNapi::Promise>(
82 "@ohos.graphics.text.getSystemFontFullNamesByType(*)",
83 {
static_cast<
int>(JsSystemFontType::INSTALLED)})
84 .withContext(std::move(resultConsumer))
86 [](
const QtOhos::CallbackInfo &cbInfo,
auto &resultConsumer) {
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 pathsCollector = std::make_shared<QOhosConsumer<std::string>>(
96 [resultConsumer = std::move(resultConsumer), pushSize = fontsNames.size(), result = std::vector<std::string>()](
auto element)
mutable {
97 result.push_back(std::move(element));
98 if (result.size() == pushSize)
99 resultConsumer(std::move(result));
102 for (
const auto &fontName : fontsNames) {
103 cbInfo.jsState().eval<QNapi::Promise>(
104 "@ohos.graphics.text.getFontDescriptorByFullName(*)",
105 {fontName,
static_cast<
int>(JsSystemFontType::INSTALLED)})
107 [pathsCollector](
const QtOhos::CallbackInfo &cbInfo) {
108 auto fontDescriptor = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
109 auto optFontPath = QNapi::getOptionalPropOrEmpty<QNapi::String>(fontDescriptor,
"path");
110 (*pathsCollector)(!optFontPath.IsEmpty() ? optFontPath.Utf8Value() :
""s);
113 [pathsCollector, fontName](
const QtOhos::CallbackInfo &cbInfo) {
114 QtOhos::logJsCallbackError(
115 cbInfo, (
"getFontDescriptorByFullName("s + fontName +
") failed"s).c_str());
116 (*pathsCollector)(
""s);
121 [](
const QtOhos::CallbackInfo &cbInfo,
auto &resultConsumer) {
122 QtOhos::logJsCallbackError(cbInfo,
"getSystemFontFullNamesByType() failed");
129 fontsPaths.begin(), fontsPaths.end(),
130 std::back_inserter(result), QString::fromStdString);
131 result.removeAll(QString());
139 if (ohosNoUiChildMode)
142 std::string defaultFontFamily;
143 auto genericFonts = jsState.eval<QNapi::Array>(
"@ohos.font.getUIFontConfig().generic");
144 if (genericFonts.Length() > 0) {
145 auto firstFont = QNapi::checkedCast<QNapi::Object>(genericFonts.Get(0U));
146 defaultFontFamily = firstFont.get<QNapi::String>(
"family");
148 qFatal(
"Failed to get system default font family name."
149 " The reason is: empty `@ohos.font.getUIFontConfig().generic` array.");
152 return defaultFontFamily;
155void registerSystemFonts()
157 QStringList fontPaths;
160 fontPaths.append(getSystemFontPaths(jsState));
161 fontPaths.append(getUIFontPaths(jsState));
163 fontPaths.append(getInstalledFontPaths());
164 fontPaths.removeDuplicates();
166 QSet<QString> uniqueFontDirs;
167 for (
const QString &fontPath : fontPaths)
168 uniqueFontDirs.insert(QFileInfo(fontPath).absolutePath());
170 FcConfig *config = FcConfigGetCurrent();
171 if (config !=
nullptr) {
172 for (
const QString &dir : uniqueFontDirs)
173 FcConfigAppFontAddDir(config,
reinterpret_cast<
const FcChar8 *>(dir.toUtf8().constData()));
174 FcConfigBuildFonts(config);
176 qOhosPrintfError(
"Failed to get fontconfig current configuration.");
185 ohosNoUiChildMode =
true;
192 registerSystemFonts();
194 QFontconfigDatabase::populateFontDatabase();
199 QFont::StyleHint styleHint,
200 QFontDatabasePrivate::ExtendedScript script)
const
204 const QFontDatabase::WritingSystem ws = qt_writing_system_for_script(script);
205 const bool defaultFontSupportsScript =
206 ws == QFontDatabase::Any ||
207 QFontDatabase::writingSystems(defaultFont().family()).contains(ws);
209 if (defaultFontSupportsScript)
210 result.append(defaultFont().family());
212 if (styleHint == QFont::Monospace || styleHint == QFont::Courier)
213 result.append(QString::fromUtf8(qgetenv(
"Droid Sans Mono;Droid Sans;Noto Sans")).split(QLatin1Char(
';')));
214 else if (styleHint == QFont::Serif)
215 result.append(QString::fromUtf8(qgetenv(
"Noto Serif")).split(QLatin1Char(
';')));
217 result.append(QString::fromUtf8(qgetenv(
"Roboto;Droid Sans")).split(QLatin1Char(
';')));
218 result.append(QFontconfigDatabase::fallbacksForFamily(family, style, styleHint, script));
225 static const char *
const preferredDefaultFontFamily =
"HarmonyOS Sans SC";
226 static const QString defaultFontFamily =
227 QFontDatabase::families().contains(QLatin1String(preferredDefaultFontFamily))
228 ? QString::fromStdString(preferredDefaultFontFamily)
229 : QtOhos::evalInJsThread(
231 return QString::fromStdString(getDefaultFontFamily(jsState));
233 return QFont(defaultFontFamily);
void runInJsThreadAndWait(const std::function< void(JsState &)> &task)
QDebug Q_GUI_EXPORT & operator<<(QDebug &s, const QVectorPath &path)