347 for (
auto it =
d->fontFamilyCollection.begin(); it !=
d->fontFamilyCollection.end(); it++) {
348 if (it->fileName == fontFamily.
fileName && it->fileIndex == fontFamily.
fileIndex) {
355 QByteArray utfData = fontFamily.
fileName.toUtf8();
356 if (FT_New_Face(freeTypeLibrary.
data(), utfData.data(), fontFamily.
fileIndex, &f) == 0) {
366 QDateTime time = QFileInfo(fontFamily.
fileName).birthTime();
367 if (time.isValid()) {
370 fontFamily.
lastModified = QDateTime::fromMSecsSinceEpoch(0);
376 if (!FT_IS_SFNT(face.
data())) {
379 fontFamily.
isItalic = face->style_flags & FT_STYLE_FLAG_ITALIC;
380 if (face->style_flags & FT_STYLE_FLAG_BOLD) {
386 for (
int i=0; i< face->num_fixed_sizes; i++) {
388 fontFamily.
pixelSizes.insert((face->available_sizes[i].size / 64.0), {fontFamily.fileName});
399 fontFamily.
isItalic = hb_style_get_value(hbFont.
data(), HB_STYLE_TAG_ITALIC) > 0;
402 TT_OS2 *os2Table =
nullptr;
403 os2Table = (TT_OS2*)FT_Get_Sfnt_Table(face.
data(), FT_SFNT_OS2);
413 if (os2Table->version >= 5) {
415 const qreal twip = 0.05;
416 sizeInfo.
high = os2Table->usUpperOpticalPointSize * twip;
417 sizeInfo.
low = os2Table->usLowerOpticalPointSize * twip;
419 sizeInfo.
isSet =
true;
432 hb_ot_name_id_t sizeNameId;
433 if (hb_ot_layout_get_size_params(hbFace.
data(), &designSize, &subFamilyId, &sizeNameId, &rangeStart, &rangeEnd)) {
436 sizeInfo.
low = rangeStart * tenth;
437 sizeInfo.
high = rangeEnd * tenth;
440 sizeInfo.
isSet =
true;
447 QHash<hb_ot_name_id_t, QString> axisNameIDs;
449 if (hb_ot_var_has_data(hbFace.
data())) {
451 uint count = hb_ot_var_get_axis_count(hbFace.
data());
454 for (
uint i = 0; i < count; i++) {
456 hb_ot_var_axis_info_t axis;
457 hb_ot_var_get_axis_infos(hbFace.
data(), i, &maxInfos, &axis);
458 axisInfo.
min = axis.min_value;
459 axisInfo.
max = axis.max_value;
460 axisInfo.
value = axis.default_value;
461 axisInfo.
axisHidden = axis.flags & HB_OT_VAR_AXIS_FLAG_HIDDEN;
463 hb_tag_to_string(axis.tag, buff);
464 axisInfo.
tag = QString::fromLatin1(buff, 4);
465 axisNameIDs.insert(axis.name_id, axisInfo.
tag);
467 fontFamily.
axes.insert(axisInfo.
tag, axisInfo);
468 axesTags.append(axisInfo.
tag);
470 count = hb_ot_var_get_named_instance_count (hbFace.
data());
471 for (
uint i = 0; i < count; i++) {
472 QHash<QString, float> instanceCoords;
473 uint coordLength = axesTags.size();
474 std::vector<float> coordinate(coordLength);
475 hb_ot_var_named_instance_get_design_coords (hbFace.
data(), i, &coordLength, coordinate.data());
476 for (
uint j =0; j < coordLength; j++ ){
477 instanceCoords.insert(axesTags.value(j), coordinate[j]);
481 instanceNameIDs.append(hb_ot_var_named_instance_get_subfamily_name_id(hbFace.
data(), i));
488 fontFamily.
colorSVG = hb_ot_color_has_svg(hbFace.
data());
496 const hb_ot_name_entry_t *entries = hb_ot_name_list_names(hbFace.
data(), &numEntries);
498 QHash<QLocale, QString> ribbiFamilyNames;
499 QHash<QLocale, QString> ribbiStyleNames;
500 QHash<QLocale, QString> WWSFamilyNames;
501 QHash<QLocale, QString> WWSStyleNames;
502 QHash<QLocale, QString> typographicFamilyNames;
503 QHash<QLocale, QString> typographicStyleNames;
504 QHash<QLocale, QString> fullNames;
505 for (
uint i = 0; i < numEntries; i++) {
506 hb_ot_name_entry_t entry = entries[i];
507 QString lang(hb_language_to_string(entry.language));
508 QLocale locale(lang);
509 uint length = hb_ot_name_get_utf8(hbFace.
data(), entry.name_id, entry.language,
nullptr,
nullptr)+1;
510 std::vector<char> buff(
length);
511 hb_ot_name_get_utf8(hbFace.
data(), entry.name_id, entry.language, &
length, buff.data());
512 QString name = QString::fromUtf8(buff.data(),
length);
513 if (name.isEmpty())
continue;
515 if (entry.name_id == HB_OT_NAME_ID_FONT_FAMILY) {
516 ribbiFamilyNames.insert(locale, name);
517 }
else if (entry.name_id == HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY) {
518 typographicFamilyNames.insert(locale, name);
519 }
else if (entry.name_id == HB_OT_NAME_ID_WWS_FAMILY) {
520 WWSFamilyNames.insert(locale, name);
521 }
else if (entry.name_id == HB_OT_NAME_ID_FONT_SUBFAMILY) {
522 ribbiStyleNames.insert(locale, name);
523 }
else if (entry.name_id == HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY) {
524 typographicStyleNames.insert(locale, name);
525 }
else if (entry.name_id == HB_OT_NAME_ID_WWS_SUBFAMILY) {
526 WWSStyleNames.insert(locale, name);
527 }
else if (entry.name_id == HB_OT_NAME_ID_FULL_NAME) {
528 fullNames.insert(locale, name);
529 }
else if (entry.name_id > 0) {
530 if (axisNameIDs.keys().contains(entry.name_id)) {
531 fontFamily.
axes[axisNameIDs.value(entry.name_id)].localizedLabels.insert(locale, name);
532 }
else if (entry.name_id == sizeNameId) {
534 }
else if (instanceNameIDs.contains(entry.name_id)) {
535 int idx = instanceNameIDs.indexOf(entry.name_id);
536 fontFamily.
styleInfo[idx].localizedLabels.insert(locale, name);
540 QLocale english(QLocale::English);
541 if (!typographicFamilyNames.isEmpty()) {
542 typographicFamily.
fontFamily = typographicFamilyNames.value(english, typographicFamilyNames.values().first());
546 if (!ribbiFamilyNames.isEmpty()) {
547 fontFamily.
fontFamily = ribbiFamilyNames.value(english, ribbiFamilyNames.values().first());
553 if (!fullNames.isEmpty() && fullNames != typographicFamilyNames) {
556 if (!ribbiStyleNames.isEmpty()) {
557 fontFamily.
fontStyle = ribbiStyleNames.value(english, ribbiStyleNames.values().first());
560 if (!WWSFamilyNames.isEmpty()) {
561 wwsFamily.
fontFamily = WWSFamilyNames.value(english, WWSFamilyNames.values().first());
575 typographicFamily.
type = typographicFamily.
type;
578 d->fontFamilyCollection.insert(
d->fontFamilyCollection.childEnd(), fontFamily);
581 auto it =
d->fontFamilyCollection.childBegin();
582 for (; it !=
d->fontFamilyCollection.childEnd(); it++) {
583 if (!typographicFamily.
fontFamily.isEmpty() && it->fontFamily == typographicFamily.
fontFamily) {
585 }
else if (it->fontFamily == fontFamily.
fontFamily) {
589 if (it !=
d->fontFamilyCollection.childEnd()) {
592 auto wws = childBegin(it);
593 for (; wws != childEnd(it); wws++) {
594 if (wws->fontFamily == wwsFamily.
fontFamily) {
598 if (wws != childEnd(it)) {
599 d->fontFamilyCollection.insert(childEnd(wws), fontFamily);
601 auto wwsNew =
d->fontFamilyCollection.insert(childEnd(it), wwsFamily);
602 d->fontFamilyCollection.insert(childEnd(wwsNew), fontFamily);
604 }
else if (!fontFamily.
pixelSizes.isEmpty()) {
606 auto pixel = childBegin(it);
607 for (; pixel != childEnd(it); pixel++) {
608 if (pixel->fontFamily == fontFamily.
fontFamily && pixel->fontStyle == fontFamily.
fontStyle && !pixel->pixelSizes.isEmpty()) {
609 for (
int pxSize = 0; pxSize < fontFamily.
pixelSizes.keys().size(); pxSize++) {
610 int px = fontFamily.
pixelSizes.keys().at(pxSize);
612 files.append(fontFamily.
pixelSizes.value(px));
613 pixel->pixelSizes.insert(px, files);
618 if (pixel == childEnd(it)) {
619 d->fontFamilyCollection.insert(childEnd(it), fontFamily);
623 d->fontFamilyCollection.insert(childEnd(it), fontFamily);
626 auto typographic =
d->fontFamilyCollection.insert(
d->fontFamilyCollection.childEnd(), typographicFamily);
628 auto wwsNew =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
629 d->fontFamilyCollection.insert(childEnd(wwsNew), fontFamily);
631 d->fontFamilyCollection.insert(childEnd(typographic), fontFamily);
675 for (
auto typographic =
d->fontFamilyCollection.childBegin(); typographic !=
d->fontFamilyCollection.childEnd(); typographic++) {
686 for (
auto child = childBegin(typographic); child != childEnd(typographic); child++) {
687 if (childBegin(child) != childEnd(child)) {
688 wwsNames.append(child->fontFamily);
693 if (!weights.contains(wght)) weights.append(wght);
695 if (!widths.contains(wdth)) widths.append(wdth);
696 if (!fileIndices.contains(child->fileIndex)) fileIndices.append(child->fileIndex);
697 types.append(child->type);
698 deleteList.append(child);
700 while (!deleteList.isEmpty()) {
701 auto child = deleteList.takeFirst();
703 d->fontFamilyCollection.erase(child);
709 if(font->fontFamily == typographic->fontFamily && font != tempList.
childBegin()) {
710 moveToFront.append(font);
713 while (!moveToFront.isEmpty()) {
714 auto font = moveToFront.takeLast();
723 const qreal testWeight = weights.contains(400)? 400: weights.first();
724 const qreal testWidth = widths.contains(100)? 100: widths.first();
726 const int testFileIndex = fileIndices.contains(0)? 0: fileIndices.first();
728 bool widthTested = !font->axes.keys().contains(
WIDTH_TAG);
731 QPair<QString, QString> fontStyle(font->fontFamily, font->fontStyle);
735 && ( ( fileIndices.size() > 1 && font->fileIndex == testFileIndex ) || ( fileIndices.size()<=1 ))
736 && font->type == testType
737 && !existing.contains(fontStyle)) {
740 existing.append(fontStyle);
742 auto newWWS =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
743 d->fontFamilyCollection.insert(childEnd(newWWS), *font);
744 deleteList.append(font);
747 while (!deleteList.isEmpty()) {
748 auto child = deleteList.takeFirst();
750 tempList.
erase(child);
754 auto wws = childBegin(typographic);
755 auto wwsCandidate = childEnd(typographic);
756 for (; wws != childEnd(typographic); wws++) {
757 auto wwsChild = childBegin(wws);
766 if (wws->fontStyle.toLower() !=
"regular"
767 && !font->fontStyle.contains(wws->fontStyle)) {
774 if (!wwsChild->sizeInfo.compare(font->sizeInfo)) {
778 for (; wwsChild != childEnd(wws); wwsChild++) {
779 if (wwsChild->isItalic == font->isItalic
780 && wwsChild->isOblique == font->isOblique
781 && wwsChild->compareAxes(font->axes)
782 && wwsChild->hasAnyColor() == font->hasAnyColor()) {
786 if (wwsChild != childEnd(wws)) {
787 if (wwsChild->fontFamily == font->fontFamily && wwsChild->fontStyle == font->fontStyle) {
792 wwsChild->otherFiles.append(wwsChild->fileName);
793 wwsChild->otherFiles.append(font->otherFiles);
794 wwsChild->fileName = font->fileName;
797 wwsChild->otherFiles.append(font->fileName);
798 wwsChild->otherFiles.append(font->otherFiles);
800 if (wwsChild->lastModified < font->lastModified) {
801 wwsChild->lastModified = font->lastModified;
811 if (wwsCandidate == childEnd(typographic)) {
814 if (wws->fontFamily == font->fontFamily) {
820 if (wwsCandidate != childEnd(typographic)) {
821 d->fontFamilyCollection.insert(childEnd(wwsCandidate), *font);
822 }
else if (wws == childEnd(typographic)) {
825 auto newWWS =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
826 if (wwsFamily.
fontFamily != typographic->fontFamily) {
827 font->localizedTypographicStyle.clear();
829 d->fontFamilyCollection.insert(childEnd(newWWS), *font);
834 if (wwsNames.contains(typographic->fontFamily) && std::distance(childBegin(typographic), childEnd(typographic)) > 1) {
835 for (
auto wws = childBegin(typographic); wws != childEnd(typographic); wws++) {
836 if (wws->fontFamily == typographic->fontFamily) {
837 if (wwsNames.contains(childBegin(wws)->fontFamily)) {
838 const QString otherWWSName = childBegin(wws)->fontFamily;
840 for (
auto otherwws = childBegin(typographic); otherwws != childEnd(typographic); otherwws++) {
841 if (otherwws->fontFamily == otherWWSName) {
842 otherwws->fontFamily = childBegin(otherwws)->fontFamily +
" " + childBegin(otherwws)->fontStyle;
843 QHash<QLocale, QString> families;
844 const QHash<QLocale, QString> styles = childBegin(otherwws)->localizedFontStyle;
845 Q_FOREACH (
const QLocale l, otherwws->localizedFontFamilies.keys()) {
846 families.insert(l, otherwws->localizedFontFamilies.value(l)+
" "+styles.value(l, childBegin(otherwws)->fontStyle));
848 otherwws->localizedFontFamilies = families;
853 wws->fontFamily = childBegin(wws)->fontFamily;
854 childBegin(wws)->localizedTypographicStyle.clear();
863 for (
auto child = childBegin(typographic); child != childEnd(typographic); child++) {
864 if (childBegin(child) != childEnd(child)) {
865 if (wwsNamesDuplicates.contains(child->fontFamily)) {
868 auto child2 = childBegin(typographic);
869 for (; child2 != childEnd(typographic); child2++) {
870 if (child2->fontFamily == child->fontFamily) {
874 if (child2 != childEnd(typographic)) {
875 for (
auto ribbi = childBegin(child); ribbi != childEnd(child); ribbi++) {
876 auto ribbi2 = childBegin(child2);
877 for (; ribbi2 != childEnd(child2); ribbi2++) {
878 if (ribbi->fontFamily == ribbi2->fontFamily && ribbi->fontStyle == ribbi2->fontStyle) {
883 if (ribbi2 != childEnd(child2)) {
884 ribbi2->otherFiles.append(ribbi->otherFiles);
885 ribbi2->otherFiles.append(ribbi->fileName);
886 ribbi2->pixelSizes.insert(ribbi->pixelSizes);
887 deleteList.append(ribbi);
889 moveList.append(ribbi);
892 while (!moveList.isEmpty()) {
893 auto move = moveList.takeFirst();
894 d->fontFamilyCollection.move(move, childEnd(child2));
899 for (
auto ribbi = childBegin(child); ribbi != childEnd(child); ribbi++) {
900 deleteList.append(ribbi);
903 deleteList.append(child);
905 wwsNamesDuplicates.append(child->fontFamily);
908 while (!deleteList.isEmpty()) {
909 auto del = deleteList.takeFirst();
911 d->fontFamilyCollection.erase(del);
1160 quint32 xRes, quint32 yRes)
const
1164 int pixelSize = info.
size * (qMin(xRes, yRes) / 72.0);
1166 Q_FOREACH(
const QString &family, info.
families) {
1167 auto it =
d->fontFamilyCollection.compositionBegin();
1168 it =
searchNodes(it,
d->fontFamilyCollection.compositionEnd(), family);
1169 if (it !=
d->fontFamilyCollection.compositionEnd()) {
1170 auto wws = siblingCurrent(it);
1176 auto hierarchy = hierarchyBegin(wws);
1179 if (hierarchy == hierarchyEnd(wws)) {
1180 auto nodes = subtreeBegin(wws);
1181 auto endNodes = subtreeEnd(wws);
1182 for (;nodes != endNodes; nodes++) {
1183 if (childBegin(nodes) == childEnd(nodes)) {
1184 candidates.append(*nodes);
1187 }
else if (childBegin(wws) == childEnd(wws)) {
1188 candidates.append(*wws);
1190 auto style = childBegin(wws);
1191 auto styleEnd = childEnd(wws);
1192 for (;style != styleEnd; style++) {
1193 candidates.append(*style);
1197 if (candidates.size() > 1) {
1202 if (candidates.size() > 1) {
1207 if (candidates.size() > 1) {
1211 if (wws->isVariable) {
1216 if (italics.isEmpty() && obliques.isEmpty()) {
1220 italics.append(node);
1222 obliques.append(node);
1228 if (info.
slantMode == QFont::StyleItalic) {
1229 if (!italics.isEmpty()) {
1230 candidates = italics;
1231 }
else if (!obliques.isEmpty()) {
1232 candidates = obliques;
1234 }
else if (info.
slantMode == QFont::StyleOblique) {
1235 if (!obliques.isEmpty()) {
1236 candidates = obliques;
1237 }
else if (!italics.isEmpty()) {
1238 candidates = italics;
1244 slantedFontFiles.append(italic.
fileName);
1247 slantedFontFiles.append(oblique.
fileName);
1250 if (!slantedFontFiles.contains(node.
fileName)) {
1251 regular.append(node);
1254 if (!regular.isEmpty()) {
1255 candidates = regular;
1261 if (candidates.size() > 1) {
1265 openType.append(node);
1268 if (!openType.isEmpty()) {
1269 candidates = openType;
1277 fileNames = node.
pixelSizes.value(pixelSize, fileNames);
1278 Q_FOREACH(
const QString &fileName, fileNames) {
1279 if (fileName.isEmpty())
continue;
1283 candidateFileNames.append(entry);
1288 return candidateFileNames;
static qreal cssSelectFontStyleValue(const QVector< qreal > &values, const qreal targetValue, const qreal defaultValue, const qreal defaultValueUpper, const bool shouldNotReturnDefault)
cssSelectFontStyleValue Select the closest font style value from the list, following the CSS Fonts se...