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);
375 bool isWWSFamilyWithoutName =
false;
377 if (!FT_IS_SFNT(face.
data())) {
380 fontFamily.
isItalic = face->style_flags & FT_STYLE_FLAG_ITALIC;
381 if (face->style_flags & FT_STYLE_FLAG_BOLD) {
387 for (
int i=0; i< face->num_fixed_sizes; i++) {
389 fontFamily.
pixelSizes.insert((face->available_sizes[i].size / 64.0), {fontFamily.fileName});
400 fontFamily.
isItalic = hb_style_get_value(hbFont.
data(), HB_STYLE_TAG_ITALIC) > 0;
403 TT_OS2 *os2Table =
nullptr;
404 os2Table = (TT_OS2*)FT_Get_Sfnt_Table(face.
data(), FT_SFNT_OS2);
414 if (os2Table->version >= 5) {
416 const qreal twip = 0.05;
417 sizeInfo.
high = os2Table->usUpperOpticalPointSize * twip;
418 sizeInfo.
low = os2Table->usLowerOpticalPointSize * twip;
420 sizeInfo.
isSet =
true;
423 isWWSFamilyWithoutName = (os2Table->fsSelection &
OS2_WWS);
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()) {
591 if (isWWSFamilyWithoutName) {
609 auto wws = childBegin(it);
610 for (; wws != childEnd(it); wws++) {
611 if (wws->fontFamily == wwsFamily.
fontFamily) {
615 if (wws != childEnd(it)) {
616 d->fontFamilyCollection.insert(childEnd(wws), fontFamily);
618 auto wwsNew =
d->fontFamilyCollection.insert(childEnd(it), wwsFamily);
619 d->fontFamilyCollection.insert(childEnd(wwsNew), fontFamily);
621 }
else if (!fontFamily.
pixelSizes.isEmpty()) {
623 auto pixel = childBegin(it);
624 for (; pixel != childEnd(it); pixel++) {
625 if (pixel->fontFamily == fontFamily.
fontFamily && pixel->fontStyle == fontFamily.
fontStyle && !pixel->pixelSizes.isEmpty()) {
626 for (
int pxSize = 0; pxSize < fontFamily.
pixelSizes.keys().size(); pxSize++) {
627 int px = fontFamily.
pixelSizes.keys().at(pxSize);
629 files.append(fontFamily.
pixelSizes.value(px));
630 pixel->pixelSizes.insert(px, files);
635 if (pixel == childEnd(it)) {
636 d->fontFamilyCollection.insert(childEnd(it), fontFamily);
640 d->fontFamilyCollection.insert(childEnd(it), fontFamily);
643 auto typographic =
d->fontFamilyCollection.insert(
d->fontFamilyCollection.childEnd(), typographicFamily);
644 if (isWWSFamilyWithoutName) {
652 auto wwsNew =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
653 d->fontFamilyCollection.insert(childEnd(wwsNew), fontFamily);
655 d->fontFamilyCollection.insert(childEnd(typographic), fontFamily);
698 for (
auto typographic =
d->fontFamilyCollection.childBegin(); typographic !=
d->fontFamilyCollection.childEnd(); typographic++) {
709 for (
auto child = childBegin(typographic); child != childEnd(typographic); child++) {
710 if (childBegin(child) != childEnd(child)) {
711 wwsNames.append(child->fontFamily);
716 if (!weights.contains(wght)) weights.append(wght);
718 if (!widths.contains(wdth)) widths.append(wdth);
719 if (!fileIndices.contains(child->fileIndex)) fileIndices.append(child->fileIndex);
720 types.append(child->type);
721 deleteList.append(child);
723 while (!deleteList.isEmpty()) {
724 auto child = deleteList.takeFirst();
726 d->fontFamilyCollection.erase(child);
733 const qreal testWeight = weights.contains(400)? 400: weights.first();
734 const qreal testWidth = widths.contains(100)? 100: widths.first();
736 const int testFileIndex = fileIndices.contains(0)? 0: fileIndices.first();
738 bool widthTested = !font->axes.keys().contains(
WIDTH_TAG);
741 QPair<QString, QString> fontStyle(font->fontFamily, font->fontStyle);
745 && ( ( fileIndices.size() > 1 && font->fileIndex == testFileIndex ) || ( fileIndices.size()<=1 ))
746 && font->type == testType
747 && !existing.contains(fontStyle)) {
750 existing.append(fontStyle);
752 auto newWWS =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
753 d->fontFamilyCollection.insert(childEnd(newWWS), *font);
754 deleteList.append(font);
757 while (!deleteList.isEmpty()) {
758 auto child = deleteList.takeFirst();
760 tempList.
erase(child);
764 auto wws = childBegin(typographic);
765 auto wwsCandidate = childEnd(typographic);
766 for (; wws != childEnd(typographic); wws++) {
767 auto wwsChild = childBegin(wws);
776 if (wws->fontStyle.toLower() !=
"regular"
777 && !font->fontStyle.contains(wws->fontStyle)) {
784 if (!wwsChild->sizeInfo.compare(font->sizeInfo)) {
788 for (; wwsChild != childEnd(wws); wwsChild++) {
789 if (wwsChild->isItalic == font->isItalic
790 && wwsChild->isOblique == font->isOblique
791 && wwsChild->compareAxes(font->axes)
792 && wwsChild->hasAnyColor() == font->hasAnyColor()) {
796 if (wwsChild != childEnd(wws)) {
797 if (wwsChild->fontFamily == font->fontFamily && wwsChild->fontStyle == font->fontStyle) {
802 wwsChild->otherFiles.append(wwsChild->fileName);
803 wwsChild->otherFiles.append(font->otherFiles);
804 wwsChild->fileName = font->fileName;
807 wwsChild->otherFiles.append(font->fileName);
808 wwsChild->otherFiles.append(font->otherFiles);
810 if (wwsChild->lastModified < font->lastModified) {
811 wwsChild->lastModified = font->lastModified;
821 if (wwsCandidate == childEnd(typographic)) {
824 if (wws->fontFamily == font->fontFamily) {
830 if (wwsCandidate != childEnd(typographic)) {
831 d->fontFamilyCollection.insert(childEnd(wwsCandidate), *font);
832 }
else if (wws == childEnd(typographic)) {
835 auto newWWS =
d->fontFamilyCollection.insert(childEnd(typographic), wwsFamily);
836 if (wwsFamily.
fontFamily != typographic->fontFamily) {
837 font->localizedTypographicStyle.clear();
839 d->fontFamilyCollection.insert(childEnd(newWWS), *font);
844 if (wwsNames.contains(typographic->fontFamily) && std::distance(childBegin(typographic), childEnd(typographic)) > 1) {
845 for (
auto wws = childBegin(typographic); wws != childEnd(typographic); wws++) {
846 if (wws->fontFamily == typographic->fontFamily) {
847 if (wwsNames.contains(childBegin(wws)->fontFamily)) {
848 const QString otherWWSName = childBegin(wws)->fontFamily;
850 for (
auto otherwws = childBegin(typographic); otherwws != childEnd(typographic); otherwws++) {
851 if (otherwws->fontFamily == otherWWSName) {
852 otherwws->fontFamily = childBegin(otherwws)->fontFamily +
" " + childBegin(otherwws)->fontStyle;
853 QHash<QLocale, QString> families;
854 const QHash<QLocale, QString> styles = childBegin(otherwws)->localizedFontStyle;
855 Q_FOREACH (
const QLocale l, otherwws->localizedFontFamilies.keys()) {
856 families.insert(l, otherwws->localizedFontFamilies.value(l)+
" "+styles.value(l, childBegin(otherwws)->fontStyle));
858 otherwws->localizedFontFamilies = families;
863 wws->fontFamily = childBegin(wws)->fontFamily;
864 childBegin(wws)->localizedTypographicStyle.clear();
1116 quint32 xRes, quint32 yRes)
const
1120 int pixelSize = info.
size * (qMin(xRes, yRes) / 72.0);
1122 Q_FOREACH(
const QString &family, info.
families) {
1123 auto it =
d->fontFamilyCollection.compositionBegin();
1124 it =
searchNodes(it,
d->fontFamilyCollection.compositionEnd(), family);
1125 if (it !=
d->fontFamilyCollection.compositionEnd()) {
1126 auto wws = siblingCurrent(it);
1132 auto hierarchy = hierarchyBegin(wws);
1135 if (hierarchy == hierarchyEnd(wws)) {
1136 auto nodes = subtreeBegin(wws);
1137 auto endNodes = subtreeEnd(wws);
1138 for (;nodes != endNodes; nodes++) {
1139 if (childBegin(nodes) == childEnd(nodes)) {
1140 candidates.append(*nodes);
1143 }
else if (childBegin(wws) == childEnd(wws)) {
1144 candidates.append(*wws);
1146 auto style = childBegin(wws);
1147 auto styleEnd = childEnd(wws);
1148 for (;style != styleEnd; style++) {
1149 candidates.append(*style);
1153 if (candidates.size() > 1) {
1158 if (candidates.size() > 1) {
1163 if (candidates.size() > 1) {
1167 if (wws->isVariable) {
1172 if (italics.isEmpty() && obliques.isEmpty()) {
1176 italics.append(node);
1178 obliques.append(node);
1184 if (info.
slantMode == QFont::StyleItalic) {
1185 if (!italics.isEmpty()) {
1186 candidates = italics;
1187 }
else if (!obliques.isEmpty()) {
1188 candidates = obliques;
1190 }
else if (info.
slantMode == QFont::StyleOblique) {
1191 if (!obliques.isEmpty()) {
1192 candidates = obliques;
1193 }
else if (!italics.isEmpty()) {
1194 candidates = italics;
1200 slantedFontFiles.append(italic.
fileName);
1203 slantedFontFiles.append(oblique.
fileName);
1206 if (!slantedFontFiles.contains(node.
fileName)) {
1207 regular.append(node);
1210 if (!regular.isEmpty()) {
1211 candidates = regular;
1217 if (candidates.size() > 1) {
1221 openType.append(node);
1224 if (!openType.isEmpty()) {
1225 candidates = openType;
1233 fileNames = node.
pixelSizes.value(pixelSize, fileNames);
1234 Q_FOREACH(
const QString &fileName, fileNames) {
1235 if (fileName.isEmpty())
continue;
1239 candidateFileNames.append(entry);
1244 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...