Improved font matching logic

This commit is contained in:
Martin Tůma 2018-11-07 22:04:11 +01:00
parent b1ed5b3a21
commit 8d1ef25105
3 changed files with 107 additions and 28 deletions

View File

@ -4,58 +4,137 @@
#include "font.h" #include "font.h"
static QList<QPair<QString, QFont::Weight> > weights()
{
QList<QPair<QString, QFont::Weight> > list;
list.append(QPair<QString, QFont::Weight>("Thin", QFont::Thin));
list.append(QPair<QString, QFont::Weight>("Extra Light", QFont::ExtraLight));
list.append(QPair<QString, QFont::Weight>("Light", QFont::Light));
list.append(QPair<QString, QFont::Weight>("Regular", QFont::Normal));
list.append(QPair<QString, QFont::Weight>("Medium", QFont::Medium));
list.append(QPair<QString, QFont::Weight>("Demi Bold", QFont::DemiBold));
list.append(QPair<QString, QFont::Weight>("Bold", QFont::Bold));
list.append(QPair<QString, QFont::Weight>("Extra Bold", QFont::ExtraBold));
list.append(QPair<QString, QFont::Weight>("Black", QFont::Black));
return list;
}
static QList<QPair<QString, QFont::Stretch> > stretches()
{
QList<QPair<QString, QFont::Stretch> > list;
list.append(QPair<QString, QFont::Stretch>("Ultra Condensed",
QFont::UltraCondensed));
list.append(QPair<QString, QFont::Stretch>("Extra Condensed",
QFont::ExtraCondensed));
list.append(QPair<QString, QFont::Stretch>("Condensed",
QFont::Condensed));
list.append(QPair<QString, QFont::Stretch>("Semi Expanded",
QFont::SemiExpanded));
list.append(QPair<QString, QFont::Stretch>("Expanded",
QFont::Expanded));
list.append(QPair<QString, QFont::Stretch>("Extra Expanded",
QFont::ExtraExpanded));
list.append(QPair<QString, QFont::Stretch>("Ultra Expanded",
QFont::UltraExpanded));
return list;
}
static QList<QPair<QString, QFont::Style> > styles()
{
QList<QPair<QString, QFont::Style> > list;
list.append(QPair<QString, QFont::Style>("Italic", QFont::StyleItalic));
list.append(QPair<QString, QFont::Style>("Oblique", QFont::StyleOblique));
return list;
}
static QList<QPair<QString, QFont::Weight> > weightList = weights();
static QList<QPair<QString, QFont::Stretch> > stretchList = stretches();
static QList<QPair<QString, QFont::Style> > styleList = styles();
static const QStringList &fonts() static const QStringList &fonts()
{ {
static QStringList l(QFontDatabase().families()); static QStringList l(QFontDatabase().families());
return l; return l;
} }
const QString fontFamily(const QString &str) static void parse(const QString &str, QString &family, QFont::Weight &weight,
QFont::Stretch &stretch, QFont::Style &style)
{ {
const QStringList &fl = fonts(); int weightIndex, stretchIndex, styleIndex, index;
weightIndex = stretchIndex = styleIndex = str.length();
QString family(str.left(str.lastIndexOf(' '))); for (int i = 0; i < weightList.size(); i++) {
for (int j = 0; j < fl.size(); j++) if ((index = str.indexOf(weightList.at(i).first)) >= 0) {
if (fl.at(j).startsWith(family)) weightIndex = index - 1;
return family; weight = weightList.at(i).second;
break;
}
}
return QString(); for (int i = 0; i < stretchList.size(); i++) {
if ((index = str.indexOf(stretchList.at(i).first)) >= 0) {
stretchIndex = index - 1;
stretch = stretchList.at(i).second;
break;
}
}
for (int i = 0; i < styleList.size(); i++) {
if ((index = str.indexOf(styleList.at(i).first)) >= 0) {
styleIndex = index - 1;
style = styleList.at(i).second;
break;
}
}
family = str.mid(0, qMin(qMin(weightIndex, stretchIndex), styleIndex));
} }
static void setType(QFont &font, const QString &str) static bool matchFamily(const QString &family)
{ {
QString type(str.right(str.length() - str.lastIndexOf(' ') - 1)); for (int j = 0; j < fonts().size(); j++)
if (fonts().at(j).startsWith(family))
return true;
if (type == "Italic") return false;
font.setItalic(true);
else if (type == "Bold")
font.setWeight(QFont::Bold);
else if (type == "Medium")
font.setWeight(QFont::Medium);
} }
QFont Font::fromJsonArray(const QJsonArray &json) QFont Font::fromJsonArray(const QJsonArray &json)
{ {
if (json.isEmpty()) if (json.isEmpty())
return QFont(); return QFont("Open Sans");
// Try exact match in order of the font list
QString family;
QFont::Weight weight = QFont::Normal;
QFont::Stretch stretch = QFont::Unstretched;
QFont::Style style = QFont::StyleNormal;
// Try exact match from the layout font list
for (int i = 0; i < json.size(); i++) { for (int i = 0; i < json.size(); i++) {
if (!json.at(i).isString()) if (!json.at(i).isString())
return QFont(); continue;
QString str(json.at(i).toString()); parse(json.at(i).toString(), family, weight, stretch, style);
QString family(fontFamily(str)); if (matchFamily(family)) {
if (!family.isNull()) {
QFont font(family); QFont font(family);
setType(font, str); font.setWeight(weight);
return font; font.setStretch(stretch);
font.setStyle(style);
} }
} }
// Use Qt's font matching logic on the first font in the list // Use Qt's font matching logic on the first font in the list
QString str(json.first().toString()); parse(json.first().toString(), family, weight, stretch, style);
QFont font(str.left(str.lastIndexOf(' ')));
setType(font, str); QFont font(family);
font.setWeight(weight);
font.setStretch(stretch);
font.setStyle(style);
return font; return font;
} }

View File

@ -273,7 +273,7 @@ bool Style::Layer::Paint::antialias(Layer::Type type, int zoom) const
Style::Layer::Layout::Layout(const QJsonObject &json) Style::Layer::Layout::Layout(const QJsonObject &json)
: _textSize(16), _textMaxWidth(10), _textMaxAngle(45), _lineCap(Qt::FlatCap), : _textSize(16), _textMaxWidth(10), _textMaxAngle(45), _lineCap(Qt::FlatCap),
_lineJoin(Qt::MiterJoin), _capitalize(false) _lineJoin(Qt::MiterJoin), _font("Open Sans"), _capitalize(false)
{ {
if (!(json.contains("text-field") && json["text-field"].isString())) if (!(json.contains("text-field") && json["text-field"].isString()))
return; return;

View File

@ -81,7 +81,7 @@ private:
public: public:
Layout() : _textSize(16), _textMaxWidth(10), _textMaxAngle(45), Layout() : _textSize(16), _textMaxWidth(10), _textMaxAngle(45),
_lineCap(Qt::FlatCap), _lineJoin(Qt::MiterJoin), _lineCap(Qt::FlatCap), _lineJoin(Qt::MiterJoin),
_capitalize(false) {} _font("Open Sans"), _capitalize(false) {}
Layout(const QJsonObject &json); Layout(const QJsonObject &json);
bool capitalize() const {return _capitalize;} bool capitalize() const {return _capitalize;}