346 for (
auto it =
d->fontFamilyCollection.begin(); it !=
d->fontFamilyCollection.end(); it++) {
347 if (it->fileName == fontFamily.
fileName && it->fileIndex == fontFamily.
fileIndex) {
354 QByteArray utfData = fontFamily.
fileName.toUtf8();
355 if (FT_New_Face(freeTypeLibrary.
data(), utfData.data(), fontFamily.
fileIndex, &f) == 0) {
366 bool isWWSFamilyWithoutName =
false;
368 if (!FT_IS_SFNT(face.
data())) {
371 fontFamily.
isItalic = face->style_flags & FT_STYLE_FLAG_ITALIC;
372 if (face->style_flags & FT_STYLE_FLAG_BOLD) {
378 for (
int i=0; i< face->num_fixed_sizes; i++) {
380 fontFamily.
pixelSizes.insert((face->available_sizes[i].size / 64.0), {fontFamily.fileName});
391 fontFamily.
isItalic = hb_style_get_value(hbFont.
data(), HB_STYLE_TAG_ITALIC) > 0;
394 TT_OS2 *os2Table =
nullptr;
395 os2Table = (TT_OS2*)FT_Get_Sfnt_Table(face.
data(), FT_SFNT_OS2);
405 if (os2Table->version >= 5) {
407 const qreal twip = 0.05;
408 sizeInfo.
high = os2Table->usUpperOpticalPointSize * twip;
409 sizeInfo.
low = os2Table->usLowerOpticalPointSize * twip;
411 sizeInfo.
isSet =
true;
414 isWWSFamilyWithoutName = (os2Table->fsSelection &
OS2_WWS);
423 hb_ot_name_id_t sizeNameId;
424 if (hb_ot_layout_get_size_params(hbFace.
data(), &designSize, &subFamilyId, &sizeNameId, &rangeStart, &rangeEnd)) {
427 sizeInfo.
low = rangeStart * tenth;
428 sizeInfo.
high = rangeEnd * tenth;
431 sizeInfo.
isSet =
true;
438 QHash<hb_ot_name_id_t, QString> axisNameIDs;
440 if (hb_ot_var_has_data(hbFace.
data())) {
442 uint count = hb_ot_var_get_axis_count(hbFace.
data());
445 for (
uint i = 0; i < count; i++) {
447 hb_ot_var_axis_info_t axis;
448 hb_ot_var_get_axis_infos(hbFace.
data(), i, &maxInfos, &axis);
449 axisInfo.
min = axis.min_value;
450 axisInfo.
max = axis.max_value;
451 axisInfo.
value = axis.default_value;
452 axisInfo.
axisHidden = axis.flags & HB_OT_VAR_AXIS_FLAG_HIDDEN;
454 hb_tag_to_string(axis.tag, buff);
455 axisInfo.
tag = QString::fromLatin1(buff, 4);
456 axisNameIDs.insert(axis.name_id, axisInfo.
tag);
458 fontFamily.
axes.insert(axisInfo.
tag, axisInfo);
459 axesTags.append(axisInfo.
tag);
461 count = hb_ot_var_get_named_instance_count (hbFace.
data());
462 for (
uint i = 0; i < count; i++) {
463 QHash<QString, float> instanceCoords;
464 uint coordLength = axesTags.size();
465 std::vector<float> coordinate(coordLength);
466 hb_ot_var_named_instance_get_design_coords (hbFace.
data(), i, &coordLength, coordinate.data());
467 for (
uint j =0; j < coordLength; j++ ){
468 instanceCoords.insert(axesTags.value(j), coordinate[j]);
472 instanceNameIDs.append(hb_ot_var_named_instance_get_subfamily_name_id(hbFace.
data(), i));
479 fontFamily.
colorSVG = hb_ot_color_has_svg(hbFace.
data());
487 const hb_ot_name_entry_t *entries = hb_ot_name_list_names(hbFace.
data(), &numEntries);
489 QHash<QLocale, QString> ribbiFamilyNames;
490 QHash<QLocale, QString> ribbiStyleNames;
491 QHash<QLocale, QString> WWSFamilyNames;
492 QHash<QLocale, QString> WWSStyleNames;
493 QHash<QLocale, QString> typographicFamilyNames;
494 QHash<QLocale, QString> typographicStyleNames;
495 QHash<QLocale, QString> fullNames;
496 for (
uint i = 0; i < numEntries; i++) {
497 hb_ot_name_entry_t entry = entries[i];
498 QString lang(hb_language_to_string(entry.language));
499 QLocale locale(lang);
500 uint length = hb_ot_name_get_utf8(hbFace.
data(), entry.name_id, entry.language,
nullptr,
nullptr)+1;
501 std::vector<char> buff(
length);
502 hb_ot_name_get_utf8(hbFace.
data(), entry.name_id, entry.language, &
length, buff.data());
503 QString name = QString::fromUtf8(buff.data(),
length);
504 if (name.isEmpty())
continue;
506 if (entry.name_id == HB_OT_NAME_ID_FONT_FAMILY) {
507 ribbiFamilyNames.insert(locale, name);
508 }
else if (entry.name_id == HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY) {
509 typographicFamilyNames.insert(locale, name);
510 }
else if (entry.name_id == HB_OT_NAME_ID_WWS_FAMILY) {
511 WWSFamilyNames.insert(locale, name);
512 }
else if (entry.name_id == HB_OT_NAME_ID_FONT_SUBFAMILY) {
513 ribbiStyleNames.insert(locale, name);
514 }
else if (entry.name_id == HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY) {
515 typographicStyleNames.insert(locale, name);
516 }
else if (entry.name_id == HB_OT_NAME_ID_WWS_SUBFAMILY) {
517 WWSStyleNames.insert(locale, name);
518 }
else if (entry.name_id == HB_OT_NAME_ID_FULL_NAME) {
519 fullNames.insert(locale, name);
520 }
else if (entry.name_id > 0) {
521 if (axisNameIDs.keys().contains(entry.name_id)) {
522 fontFamily.
axes[axisNameIDs.value(entry.name_id)].localizedLabels.insert(locale, name);
523 }
else if (entry.name_id == sizeNameId) {
525 }
else if (instanceNameIDs.contains(entry.name_id)) {
526 int idx = instanceNameIDs.indexOf(entry.name_id);
527 fontFamily.
styleInfo[idx].localizedLabels.insert(locale, name);
531 QLocale english(QLocale::English);
532 if (!typographicFamilyNames.isEmpty()) {
533 typographicFamily.
fontFamily = typographicFamilyNames.value(english, typographicFamilyNames.values().first());
537 if (!ribbiFamilyNames.isEmpty()) {
538 fontFamily.
fontFamily = ribbiFamilyNames.value(english, ribbiFamilyNames.values().first());
544 if (!fullNames.isEmpty() && fullNames != typographicFamilyNames) {
547 if (!ribbiStyleNames.isEmpty()) {
548 fontFamily.
fontStyle = ribbiStyleNames.value(english, ribbiStyleNames.values().first());
551 if (!WWSFamilyNames.isEmpty()) {
552 wwsFamily.
fontFamily = WWSFamilyNames.value(english, WWSFamilyNames.values().first());
566 typographicFamily.
type = typographicFamily.
type;
569 d->fontFamilyCollection.insert(
d->fontFamilyCollection.childEnd(), fontFamily);
572 auto it =
d->fontFamilyCollection.childBegin();
573 for (; it !=
d->fontFamilyCollection.childEnd(); it++) {
574 if (!typographicFamily.
fontFamily.isEmpty() && it->fontFamily == typographicFamily.
fontFamily) {
576 }
else if (it->fontFamily == fontFamily.
fontFamily) {
580 if (it !=
d->fontFamilyCollection.childEnd()) {
582 if (isWWSFamilyWithoutName) {
587 auto wws = childBegin(it);
588 for (; wws != childEnd(it); wws++) {
589 if (wws->fontFamily == wwsFamily.
fontFamily) {
593 if (wws != childEnd(it)) {
594 d->fontFamilyCollection.insert(childEnd(wws), fontFamily);
596 auto wwsNew =
d->fontFamilyCollection.insert(childEnd(it), wwsFamily);
597 d->fontFamilyCollection.insert(childEnd(wwsNew), fontFamily);
599 }
else if (!fontFamily.
pixelSizes.isEmpty()) {
601 auto pixel = childBegin(it);
602 for (; pixel != childEnd(it); pixel++) {
603 if (pixel->fontFamily == fontFamily.
fontFamily && pixel->fontStyle == fontFamily.
fontStyle && !pixel->pixelSizes.isEmpty()) {
604 for (
int pxSize = 0; pxSize < fontFamily.
pixelSizes.keys().size(); pxSize++) {
605 int px = fontFamily.
pixelSizes.keys().at(pxSize);
607 files.append(fontFamily.
pixelSizes.value(px));
608 pixel->pixelSizes.insert(px, files);
613 if (pixel == childEnd(it)) {
614 d->fontFamilyCollection.insert(childEnd(it), fontFamily);
618 d->fontFamilyCollection.insert(childEnd(it), fontFamily);
621 auto typographic =
d->fontFamilyCollection.insert(
d->fontFamilyCollection.childEnd(), typographicFamily);
622 if (isWWSFamilyWithoutName) {
626 auto wwsNew =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
627 d->fontFamilyCollection.insert(childEnd(wwsNew), fontFamily);
629 d->fontFamilyCollection.insert(childEnd(typographic), fontFamily);
672 for (
auto typographic =
d->fontFamilyCollection.childBegin(); typographic !=
d->fontFamilyCollection.childEnd(); typographic++) {
683 for (
auto child = childBegin(typographic); child != childEnd(typographic); child++) {
684 if (childBegin(child) != childEnd(child)) {
685 wwsNames.append(child->fontFamily);
690 if (!weights.contains(wght)) weights.append(wght);
692 if (!widths.contains(wdth)) widths.append(wdth);
693 if (!fileIndices.contains(child->fileIndex)) fileIndices.append(child->fileIndex);
694 types.append(child->type);
695 deleteList.append(child);
697 while (!deleteList.isEmpty()) {
698 auto child = deleteList.takeFirst();
700 d->fontFamilyCollection.erase(child);
707 const qreal testWeight = weights.contains(400)? 400: weights.first();
708 const qreal testWidth = widths.contains(100)? 100: widths.first();
710 const int testFileIndex = fileIndices.contains(0)? 0: fileIndices.first();
712 bool widthTested = !font->axes.keys().contains(
WIDTH_TAG);
715 QPair<QString, QString> fontStyle(font->fontFamily, font->fontStyle);
719 && ( ( fileIndices.size() > 1 && font->fileIndex == testFileIndex ) || ( fileIndices.size()<=1 ))
720 && font->type == testType
721 && !existing.contains(fontStyle)) {
724 existing.append(fontStyle);
726 auto newWWS =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
727 d->fontFamilyCollection.insert(childEnd(newWWS), *font);
728 deleteList.append(font);
731 while (!deleteList.isEmpty()) {
732 auto child = deleteList.takeFirst();
734 tempList.
erase(child);
738 auto wws = childBegin(typographic);
739 auto wwsCandidate = childEnd(typographic);
740 for (; wws != childEnd(typographic); wws++) {
741 auto wwsChild = childBegin(wws);
750 if (wws->fontStyle.toLower() !=
"regular"
751 && !font->fontStyle.contains(wws->fontStyle)) {
758 if (!wwsChild->sizeInfo.compare(font->sizeInfo)) {
762 for (; wwsChild != childEnd(wws); wwsChild++) {
763 if (wwsChild->isItalic == font->isItalic
764 && wwsChild->isOblique == font->isOblique
765 && wwsChild->compareAxes(font->axes)
766 && wwsChild->hasAnyColor() == font->hasAnyColor()) {
770 if (wwsChild != childEnd(wws)) {
771 if (wwsChild->fontFamily == font->fontFamily && wwsChild->fontStyle == font->fontStyle) {
776 wwsChild->otherFiles.append(wwsChild->fileName);
777 wwsChild->otherFiles.append(font->otherFiles);
778 wwsChild->fileName = font->fileName;
781 wwsChild->otherFiles.append(font->fileName);
782 wwsChild->otherFiles.append(font->otherFiles);
784 if (wwsChild->lastModified < font->lastModified) {
785 wwsChild->lastModified = font->lastModified;
795 if (wwsCandidate == childEnd(typographic)) {
798 if (wws->fontFamily == font->fontFamily) {
804 if (wwsCandidate != childEnd(typographic)) {
805 d->fontFamilyCollection.insert(childEnd(wwsCandidate), *font);
806 }
else if (wws == childEnd(typographic)) {
809 auto newWWS =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
810 if (wwsFamily.
fontFamily != typographic->fontFamily) {
811 font->localizedTypographicStyle.clear();
813 d->fontFamilyCollection.insert(childEnd(newWWS), *font);
818 if (wwsNames.contains(typographic->fontFamily) && std::distance(childBegin(typographic), childEnd(typographic)) > 1) {
819 for (
auto wws = childBegin(typographic); wws != childEnd(typographic); wws++) {
820 if (wws->fontFamily == typographic->fontFamily) {
821 if (wwsNames.contains(childBegin(wws)->fontFamily)) {
822 const QString otherWWSName = childBegin(wws)->fontFamily;
824 for (
auto otherwws = childBegin(typographic); otherwws != childEnd(typographic); otherwws++) {
825 if (otherwws->fontFamily == otherWWSName) {
826 otherwws->fontFamily = childBegin(otherwws)->fontFamily +
" " + childBegin(otherwws)->fontStyle;
827 QHash<QLocale, QString> families;
828 const QHash<QLocale, QString> styles = childBegin(otherwws)->localizedFontStyle;
829 Q_FOREACH (
const QLocale l, otherwws->localizedFontFamilies.keys()) {
830 families.insert(l, otherwws->localizedFontFamilies.value(l)+
" "+styles.value(l, childBegin(otherwws)->fontStyle));
832 otherwws->localizedFontFamilies = families;
837 wws->fontFamily = childBegin(wws)->fontFamily;
838 childBegin(wws)->localizedTypographicStyle.clear();
1082 quint32 xRes, quint32 yRes)
const
1086 int pixelSize = info.
size * (qMin(xRes, yRes) / 72.0);
1088 Q_FOREACH(
const QString &family, info.
families) {
1089 auto it =
d->fontFamilyCollection.compositionBegin();
1090 it =
searchNodes(it,
d->fontFamilyCollection.compositionEnd(), family);
1091 if (it !=
d->fontFamilyCollection.compositionEnd()) {
1092 auto wws = siblingCurrent(it);
1098 auto hierarchy = hierarchyBegin(wws);
1101 if (hierarchy == hierarchyEnd(wws)) {
1102 auto nodes = subtreeBegin(wws);
1103 auto endNodes = subtreeEnd(wws);
1104 for (;nodes != endNodes; nodes++) {
1105 if (childBegin(nodes) == childEnd(nodes)) {
1106 candidates.append(*nodes);
1109 }
else if (childBegin(wws) == childEnd(wws)) {
1110 candidates.append(*wws);
1112 auto style = childBegin(wws);
1113 auto styleEnd = childEnd(wws);
1114 for (;style != styleEnd; style++) {
1115 candidates.append(*style);
1119 if (candidates.size() > 1) {
1124 if (candidates.size() > 1) {
1129 if (candidates.size() > 1) {
1133 if (wws->isVariable) {
1138 if (italics.isEmpty() && obliques.isEmpty()) {
1142 italics.append(node);
1144 obliques.append(node);
1150 if (info.
slantMode == QFont::StyleItalic) {
1151 if (!italics.isEmpty()) {
1152 candidates = italics;
1153 }
else if (!obliques.isEmpty()) {
1154 candidates = obliques;
1156 }
else if (info.
slantMode == QFont::StyleOblique) {
1157 if (!obliques.isEmpty()) {
1158 candidates = obliques;
1159 }
else if (!italics.isEmpty()) {
1160 candidates = italics;
1166 slantedFontFiles.append(italic.
fileName);
1169 slantedFontFiles.append(oblique.
fileName);
1172 if (!slantedFontFiles.contains(node.
fileName)) {
1173 regular.append(node);
1176 if (!regular.isEmpty()) {
1177 candidates = regular;
1183 if (candidates.size() > 1) {
1187 openType.append(node);
1190 if (!openType.isEmpty()) {
1191 candidates = openType;
1199 fileNames = node.
pixelSizes.value(pixelSize, fileNames);
1200 Q_FOREACH(
const QString &fileName, fileNames) {
1201 if (fileName.isEmpty())
continue;
1205 candidateFileNames.append(entry);
1210 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...