Charlie Jiang pushed to branch gsoc-2022-chariri-3 at FreeType / FreeType Demo Programs
Commits:
-
3f5ab935
by Charlie Jiang at 2022-08-11T23:50:23+08:00
-
42cabc80
by Charlie Jiang at 2022-08-14T23:53:56+08:00
14 changed files:
- src/ftinspect/CMakeLists.txt
- src/ftinspect/engine/charmap.cpp
- src/ftinspect/engine/charmap.hpp
- src/ftinspect/engine/engine.cpp
- src/ftinspect/engine/engine.hpp
- + src/ftinspect/engine/fontinfo.cpp
- + src/ftinspect/engine/fontinfo.hpp
- src/ftinspect/maingui.cpp
- src/ftinspect/maingui.hpp
- src/ftinspect/meson.build
- + src/ftinspect/models/fontinfomodels.cpp
- + src/ftinspect/models/fontinfomodels.hpp
- + src/ftinspect/panels/info.cpp
- + src/ftinspect/panels/info.hpp
Changes:
... | ... | @@ -25,6 +25,7 @@ add_executable(ftinspect |
25 | 25 | "engine/charmap.cpp"
|
26 | 26 | "engine/paletteinfo.cpp"
|
27 | 27 | "engine/stringrenderer.cpp"
|
28 | + "engine/fontinfo.cpp"
|
|
28 | 29 | |
29 | 30 | "rendering/glyphbitmap.cpp"
|
30 | 31 | "rendering/glyphoutline.cpp"
|
... | ... | @@ -42,11 +43,13 @@ add_executable(ftinspect |
42 | 43 | "widgets/charmapcombobox.cpp"
|
43 | 44 | |
44 | 45 | "models/customcomboboxmodels.cpp"
|
46 | + "models/fontinfomodels.cpp"
|
|
45 | 47 | |
46 | 48 | "panels/settingpanel.cpp"
|
47 | 49 | "panels/singular.cpp"
|
48 | 50 | "panels/continuous.cpp"
|
49 | 51 | "panels/comparator.cpp"
|
52 | + "panels/info.cpp"
|
|
50 | 53 | "panels/glyphdetails.cpp"
|
51 | 54 | )
|
52 | 55 | target_link_libraries(ftinspect
|
... | ... | @@ -5,6 +5,8 @@ |
5 | 5 | #include "charmap.hpp"
|
6 | 6 | |
7 | 7 | #include <QHash>
|
8 | +#include <freetype/freetype.h>
|
|
9 | +#include <freetype/tttables.h>
|
|
8 | 10 | |
9 | 11 | QHash<FT_Encoding, QString> encodingNamesCache;
|
10 | 12 | QHash<FT_Encoding, QString>&
|
... | ... | @@ -37,7 +39,10 @@ encodingNames() |
37 | 39 | CharMapInfo::CharMapInfo(int index, FT_CharMap cmap)
|
38 | 40 | : index(index), ptr(cmap),
|
39 | 41 | encoding(cmap->encoding),
|
40 | - platformID(cmap->platform_id), encodingID(cmap->encoding_id),
|
|
42 | + platformID(cmap->platform_id),
|
|
43 | + encodingID(cmap->encoding_id),
|
|
44 | + formatID(FT_Get_CMap_Format(cmap)),
|
|
45 | + languageID(FT_Get_CMap_Language_ID(cmap)),
|
|
41 | 46 | maxIndex(-1)
|
42 | 47 | {
|
43 | 48 | auto& names = encodingNames();
|
... | ... | @@ -19,6 +19,8 @@ struct CharMapInfo |
19 | 19 | FT_Encoding encoding;
|
20 | 20 | unsigned short platformID;
|
21 | 21 | unsigned short encodingID;
|
22 | + long formatID;
|
|
23 | + unsigned long languageID;
|
|
22 | 24 | QString* encodingName;
|
23 | 25 | |
24 | 26 | // Actually this shouldn't go here, but for convenience...
|
... | ... | @@ -33,7 +35,13 @@ struct CharMapInfo |
33 | 35 | friend bool
|
34 | 36 | operator==(const CharMapInfo& lhs, const CharMapInfo& rhs)
|
35 | 37 | {
|
36 | - return lhs.index == rhs.index && lhs.encoding == rhs.encoding;
|
|
38 | + // omitting `ptr` by design!
|
|
39 | + return lhs.index == rhs.index
|
|
40 | + && lhs.encoding == rhs.encoding
|
|
41 | + && lhs.platformID == rhs.platformID
|
|
42 | + && lhs.encodingID == rhs.encodingID
|
|
43 | + && lhs.formatID == rhs.formatID
|
|
44 | + && lhs.languageID == rhs.languageID;
|
|
37 | 45 | }
|
38 | 46 | |
39 | 47 |
... | ... | @@ -9,6 +9,7 @@ |
9 | 9 | #include "../rendering/graphicsdefault.hpp"
|
10 | 10 | |
11 | 11 | #include <stdexcept>
|
12 | +#include <cmath>
|
|
12 | 13 | #include <stdint.h>
|
13 | 14 | |
14 | 15 | #include <freetype/ftmodapi.h>
|
... | ... | @@ -282,6 +283,7 @@ Engine::loadFont(int fontIndex, |
282 | 283 | |
283 | 284 | update();
|
284 | 285 | |
286 | + curFontIndex_ = fontIndex;
|
|
285 | 287 | auto id = FaceID(fontIndex, faceIndex, namedInstanceIndex);
|
286 | 288 | |
287 | 289 | // search triplet (fontIndex, faceIndex, namedInstanceIndex)
|
... | ... | @@ -912,26 +914,26 @@ Engine::calculateForegroundTable() |
912 | 914 | // Yes I know this is horribly slow, but we're only calculating the table once
|
913 | 915 | // and can use it for all rendering if the color and gamma isn't changing.
|
914 | 916 | |
915 | - double br = pow(qRed(backgroundColor_) / 255.0, gamma_);
|
|
916 | - double bg = pow(qGreen(backgroundColor_) / 255.0, gamma_);
|
|
917 | - double bb = pow(qBlue(backgroundColor_) / 255.0, gamma_);
|
|
917 | + double br = std::pow(qRed(backgroundColor_) / 255.0, gamma_);
|
|
918 | + double bg = std::pow(qGreen(backgroundColor_) / 255.0, gamma_);
|
|
919 | + double bb = std::pow(qBlue(backgroundColor_) / 255.0, gamma_);
|
|
918 | 920 | double invGamma = 1 / gamma_;
|
919 | 921 | |
920 | 922 | for (int i = 0; i <= 0xFF; i++)
|
921 | 923 | {
|
922 | 924 | double foreAlpha = i * qAlpha(foregroundColor_) / 255.0 / 255.0;
|
923 | 925 | double backAlpha = 1 - foreAlpha;
|
924 | - double r = pow(qRed(foregroundColor_) / 255.0, gamma_);
|
|
925 | - double g = pow(qGreen(foregroundColor_) / 255.0, gamma_);
|
|
926 | - double b = pow(qBlue(foregroundColor_) / 255.0, gamma_);
|
|
926 | + double r = std::pow(qRed(foregroundColor_) / 255.0, gamma_);
|
|
927 | + double g = std::pow(qGreen(foregroundColor_) / 255.0, gamma_);
|
|
928 | + double b = std::pow(qBlue(foregroundColor_) / 255.0, gamma_);
|
|
927 | 929 | |
928 | 930 | r = br * backAlpha + r * foreAlpha;
|
929 | 931 | g = bg * backAlpha + g * foreAlpha;
|
930 | 932 | b = bb * backAlpha + b * foreAlpha;
|
931 | 933 | |
932 | - r = pow(r, invGamma);
|
|
933 | - g = pow(g, invGamma);
|
|
934 | - b = pow(b, invGamma);
|
|
934 | + r = std::pow(r, invGamma);
|
|
935 | + g = std::pow(g, invGamma);
|
|
936 | + b = std::pow(b, invGamma);
|
|
935 | 937 | |
936 | 938 | foregroundTable_[i]
|
937 | 939 | = qRgba(static_cast<int>(r * 255),
|
... | ... | @@ -129,6 +129,8 @@ public: |
129 | 129 | double pointSize() { return pointSize_; }
|
130 | 130 | |
131 | 131 | int numberOfOpenedFonts();
|
132 | + int currentFontIndex() { return curFontIndex_; }
|
|
133 | + FT_Size currentFtSize() { return ftSize_; }
|
|
132 | 134 | int currentFontType() const { return fontType_; }
|
133 | 135 | const QString& currentFamilyName() { return curFamilyName_; }
|
134 | 136 | const QString& currentStyleName() { return curStyleName_; }
|
... | ... | @@ -215,6 +217,7 @@ private: |
215 | 217 | |
216 | 218 | FontFileManager fontFileManager_;
|
217 | 219 | |
220 | + int curFontIndex_ = -1;
|
|
218 | 221 | QString curFamilyName_;
|
219 | 222 | QString curStyleName_;
|
220 | 223 | int curNumGlyphs_ = -1;
|
1 | +// fontinfo.cpp
|
|
2 | + |
|
3 | +// Copyright (C) 2022 by Charlie Jiang.
|
|
4 | + |
|
5 | +#include "fontinfo.hpp"
|
|
6 | + |
|
7 | +#include "engine.hpp"
|
|
8 | + |
|
9 | +#include <freetype/ftmodapi.h>
|
|
10 | +#include <freetype/tttables.h>
|
|
11 | + |
|
12 | + |
|
13 | +FontBasicInfo
|
|
14 | +FontBasicInfo::get(Engine* engine)
|
|
15 | +{
|
|
16 | + auto fontIndex = engine->currentFontIndex();
|
|
17 | + if (fontIndex < 0)
|
|
18 | + return {};
|
|
19 | + FontBasicInfo result;
|
|
20 | + result.numFaces = engine->numberOfFaces(fontIndex);
|
|
21 | + |
|
22 | + engine->reloadFont();
|
|
23 | + auto size = engine->currentFtSize();
|
|
24 | + if (!size)
|
|
25 | + return result;
|
|
26 | + |
|
27 | + auto face = size->face;
|
|
28 | + if (face->family_name)
|
|
29 | + result.familyName = QString(face->family_name);
|
|
30 | + if (face->style_name)
|
|
31 | + result.styleName = QString(face->style_name);
|
|
32 | + |
|
33 | + auto psName = FT_Get_Postscript_Name(face);
|
|
34 | + if (psName)
|
|
35 | + result.postscriptName = QString(psName);
|
|
36 | + |
|
37 | + auto head = static_cast<TT_Header*>(FT_Get_Sfnt_Table(face, FT_SFNT_HEAD));
|
|
38 | + if (head)
|
|
39 | + {
|
|
40 | + uint64_t createdTimestamp
|
|
41 | + = head->Created[1] | static_cast<uint64_t>(head->Created[0]) << 32;
|
|
42 | + uint64_t modifiedTimestamp
|
|
43 | + = head->Modified[1] | static_cast<uint64_t>(head->Modified[0]) << 32;
|
|
44 | +
|
|
45 | + result.createdTime
|
|
46 | + = QDateTime::fromSecsSinceEpoch(createdTimestamp, Qt::OffsetFromUTC)
|
|
47 | + .addSecs(-2082844800);
|
|
48 | + result.modifiedTime
|
|
49 | + = QDateTime::fromSecsSinceEpoch(modifiedTimestamp, Qt::OffsetFromUTC)
|
|
50 | + .addSecs(-2082844800);
|
|
51 | + |
|
52 | + auto revDouble = head->Font_Revision / 65536.0;
|
|
53 | + if (head->Font_Revision & 0xFFC0)
|
|
54 | + result.revision = QString::number(revDouble, 'g', 4);
|
|
55 | + else
|
|
56 | + result.revision = QString::number(revDouble, 'g', 2);
|
|
57 | + }
|
|
58 | + |
|
59 | + return result;
|
|
60 | +}
|
|
61 | + |
|
62 | + |
|
63 | +FontTypeEntries
|
|
64 | +FontTypeEntries::get(Engine* engine)
|
|
65 | +{
|
|
66 | + engine->reloadFont();
|
|
67 | + auto size = engine->currentFtSize();
|
|
68 | + if (!size)
|
|
69 | + return {};
|
|
70 | + |
|
71 | + auto face = size->face;
|
|
72 | + |
|
73 | + FontTypeEntries result = {};
|
|
74 | + result.driverName = QString(FT_FACE_DRIVER_NAME(face));
|
|
75 | + result.sfnt = FT_IS_SFNT(face);
|
|
76 | + result.scalable = FT_IS_SCALABLE(face);
|
|
77 | + if (result.scalable)
|
|
78 | + result.mmgx = FT_HAS_MULTIPLE_MASTERS(face);
|
|
79 | + else
|
|
80 | + result.mmgx = false;
|
|
81 | + result.fixedSizes = FT_HAS_FIXED_SIZES(face);
|
|
82 | + result.hasHorizontal = FT_HAS_HORIZONTAL(face);
|
|
83 | + result.hasVertical = FT_HAS_VERTICAL(face);
|
|
84 | + result.fixedWidth = FT_IS_FIXED_WIDTH(face);
|
|
85 | + result.glyphNames = FT_HAS_GLYPH_NAMES(face);
|
|
86 | + |
|
87 | + if (result.scalable)
|
|
88 | + {
|
|
89 | + result.emSize = face->units_per_EM;
|
|
90 | + result.globalBBox = face->bbox;
|
|
91 | + result.ascender = face->ascender;
|
|
92 | + result.descender = face->descender;
|
|
93 | + result.height = face->height;
|
|
94 | + result.maxAdvanceWidth = face->max_advance_width;
|
|
95 | + result.maxAdvanceHeight = face->max_advance_height;
|
|
96 | + result.underlinePos = face->underline_position;
|
|
97 | + result.underlineThickness = face->underline_thickness;
|
|
98 | + }
|
|
99 | + |
|
100 | + return result;
|
|
101 | +}
|
|
102 | + |
|
103 | + |
|
104 | +bool
|
|
105 | +FontFixedSize::get(Engine* engine,
|
|
106 | + std::vector<FontFixedSize>& list,
|
|
107 | + const std::function<void()>& onUpdateNeeded)
|
|
108 | +{
|
|
109 | + engine->reloadFont();
|
|
110 | + auto size = engine->currentFtSize();
|
|
111 | + if (!size)
|
|
112 | + {
|
|
113 | + if (list.empty())
|
|
114 | + return false;
|
|
115 | + |
|
116 | + onUpdateNeeded();
|
|
117 | + list.clear();
|
|
118 | + return true;
|
|
119 | + }
|
|
120 | + |
|
121 | + auto face = size->face;
|
|
122 | + auto changed = false;
|
|
123 | + if (list.size() != static_cast<size_t>(face->num_fixed_sizes))
|
|
124 | + {
|
|
125 | + changed = true;
|
|
126 | + onUpdateNeeded();
|
|
127 | + list.resize(face->num_fixed_sizes);
|
|
128 | + }
|
|
129 | + |
|
130 | + for (int i = 0; i < face->num_fixed_sizes; ++i)
|
|
131 | + {
|
|
132 | + FontFixedSize ffs = {};
|
|
133 | + auto bSize = face->available_sizes + i;
|
|
134 | + ffs.height = bSize->height;
|
|
135 | + ffs.width = bSize->width;
|
|
136 | + ffs.size = bSize->size / 64.0;
|
|
137 | + ffs.xPpem = bSize->x_ppem / 64.0;
|
|
138 | + ffs.yPpem = bSize->y_ppem / 64.0;
|
|
139 | + if (ffs != list[i])
|
|
140 | + {
|
|
141 | +
|
|
142 | + if (!changed)
|
|
143 | + {
|
|
144 | + onUpdateNeeded();
|
|
145 | + changed = true;
|
|
146 | + }
|
|
147 | +
|
|
148 | + list[i] = ffs;
|
|
149 | + }
|
|
150 | + }
|
|
151 | + |
|
152 | + return changed;
|
|
153 | +}
|
|
154 | + |
|
155 | + |
|
156 | +// end of fontinfo.cpp |
1 | +// fontinfo.hpp
|
|
2 | + |
|
3 | +// Copyright (C) 2022 by Charlie Jiang.
|
|
4 | + |
|
5 | +#pragma once
|
|
6 | + |
|
7 | +#include <QDateTime>
|
|
8 | +#include <QString>
|
|
9 | +#include <freetype/freetype.h>
|
|
10 | + |
|
11 | +class Engine;
|
|
12 | + |
|
13 | +struct SFNTNameTable
|
|
14 | +{
|
|
15 | +
|
|
16 | +};
|
|
17 | + |
|
18 | +struct FontBasicInfo
|
|
19 | +{
|
|
20 | + int numFaces = -1;
|
|
21 | + QString familyName;
|
|
22 | + QString styleName;
|
|
23 | + QString postscriptName;
|
|
24 | + QDateTime createdTime;
|
|
25 | + QDateTime modifiedTime;
|
|
26 | + QString revision;
|
|
27 | + QString copyright;
|
|
28 | + QString trademark;
|
|
29 | + QString manufacturer;
|
|
30 | + |
|
31 | + static FontBasicInfo get(Engine* engine);
|
|
32 | + |
|
33 | + |
|
34 | + // Oh, we have no C++20 :(
|
|
35 | + friend bool
|
|
36 | + operator==(const FontBasicInfo& lhs,
|
|
37 | + const FontBasicInfo& rhs)
|
|
38 | + {
|
|
39 | + return lhs.numFaces == rhs.numFaces
|
|
40 | + && lhs.familyName == rhs.familyName
|
|
41 | + && lhs.styleName == rhs.styleName
|
|
42 | + && lhs.postscriptName == rhs.postscriptName
|
|
43 | + && lhs.createdTime == rhs.createdTime
|
|
44 | + && lhs.modifiedTime == rhs.modifiedTime
|
|
45 | + && lhs.revision == rhs.revision
|
|
46 | + && lhs.copyright == rhs.copyright
|
|
47 | + && lhs.trademark == rhs.trademark
|
|
48 | + && lhs.manufacturer == rhs.manufacturer;
|
|
49 | + }
|
|
50 | + |
|
51 | + |
|
52 | + friend bool
|
|
53 | + operator!=(const FontBasicInfo& lhs,
|
|
54 | + const FontBasicInfo& rhs)
|
|
55 | + {
|
|
56 | + return !(lhs == rhs);
|
|
57 | + }
|
|
58 | +};
|
|
59 | + |
|
60 | + |
|
61 | +struct FontTypeEntries
|
|
62 | +{
|
|
63 | + QString driverName;
|
|
64 | + bool sfnt : 1;
|
|
65 | + bool scalable : 1;
|
|
66 | + bool mmgx : 1;
|
|
67 | + bool fixedSizes : 1;
|
|
68 | + bool hasHorizontal : 1;
|
|
69 | + bool hasVertical : 1;
|
|
70 | + bool fixedWidth : 1;
|
|
71 | + bool glyphNames : 1;
|
|
72 | + |
|
73 | + int emSize;
|
|
74 | + FT_BBox globalBBox;
|
|
75 | + int ascender;
|
|
76 | + int descender;
|
|
77 | + int height;
|
|
78 | + int maxAdvanceWidth;
|
|
79 | + int maxAdvanceHeight;
|
|
80 | + int underlinePos;
|
|
81 | + int underlineThickness;
|
|
82 | + |
|
83 | + static FontTypeEntries get(Engine* engine);
|
|
84 | + |
|
85 | + |
|
86 | + // Oh, we have no C++20 :(
|
|
87 | + friend bool
|
|
88 | + operator==(const FontTypeEntries& lhs,
|
|
89 | + const FontTypeEntries& rhs)
|
|
90 | + {
|
|
91 | + return lhs.driverName == rhs.driverName
|
|
92 | + && lhs.sfnt == rhs.sfnt
|
|
93 | + && lhs.scalable == rhs.scalable
|
|
94 | + && lhs.mmgx == rhs.mmgx
|
|
95 | + && lhs.fixedSizes == rhs.fixedSizes
|
|
96 | + && lhs.hasHorizontal == rhs.hasHorizontal
|
|
97 | + && lhs.hasVertical == rhs.hasVertical
|
|
98 | + && lhs.fixedWidth == rhs.fixedWidth
|
|
99 | + && lhs.glyphNames == rhs.glyphNames
|
|
100 | + && lhs.emSize == rhs.emSize
|
|
101 | + && lhs.globalBBox.xMax == rhs.globalBBox.xMax
|
|
102 | + && lhs.globalBBox.xMin == rhs.globalBBox.xMin
|
|
103 | + && lhs.globalBBox.yMax == rhs.globalBBox.yMax
|
|
104 | + && lhs.globalBBox.yMin == rhs.globalBBox.yMin
|
|
105 | + && lhs.ascender == rhs.ascender
|
|
106 | + && lhs.descender == rhs.descender
|
|
107 | + && lhs.height == rhs.height
|
|
108 | + && lhs.maxAdvanceWidth == rhs.maxAdvanceWidth
|
|
109 | + && lhs.maxAdvanceHeight == rhs.maxAdvanceHeight
|
|
110 | + && lhs.underlinePos == rhs.underlinePos
|
|
111 | + && lhs.underlineThickness == rhs.underlineThickness;
|
|
112 | + }
|
|
113 | + |
|
114 | + |
|
115 | + friend bool
|
|
116 | + operator!=(const FontTypeEntries& lhs,
|
|
117 | + const FontTypeEntries& rhs)
|
|
118 | + {
|
|
119 | + return !(lhs == rhs);
|
|
120 | + }
|
|
121 | +};
|
|
122 | + |
|
123 | + |
|
124 | +struct FontFixedSize
|
|
125 | +{
|
|
126 | + short height;
|
|
127 | + short width;
|
|
128 | + double size;
|
|
129 | + double xPpem;
|
|
130 | + double yPpem;
|
|
131 | + |
|
132 | + |
|
133 | + // Returns that if the list is updated
|
|
134 | + // Using a callback because Qt needs `beginResetModel` to be called **before**
|
|
135 | + // the internal storage updates.
|
|
136 | + static bool get(Engine* engine,
|
|
137 | + std::vector<FontFixedSize>& list,
|
|
138 | + const std::function<void()>& onUpdateNeeded);
|
|
139 | + |
|
140 | + |
|
141 | + friend bool
|
|
142 | + operator==(const FontFixedSize& lhs,
|
|
143 | + const FontFixedSize& rhs)
|
|
144 | + {
|
|
145 | + return lhs.height == rhs.height
|
|
146 | + && lhs.width == rhs.width
|
|
147 | + && lhs.size == rhs.size
|
|
148 | + && lhs.xPpem == rhs.xPpem
|
|
149 | + && lhs.yPpem == rhs.yPpem;
|
|
150 | + }
|
|
151 | + |
|
152 | + |
|
153 | + friend bool
|
|
154 | + operator!=(const FontFixedSize& lhs,
|
|
155 | + const FontFixedSize& rhs)
|
|
156 | + {
|
|
157 | + return !(lhs == rhs);
|
|
158 | + }
|
|
159 | +};
|
|
160 | + |
|
161 | + |
|
162 | +// end of fontinfo.hpp |
... | ... | @@ -240,6 +240,7 @@ MainGUI::createLayout() |
240 | 240 | continuousTab_ = new ContinuousTab(this, engine_,
|
241 | 241 | glyphDetailsDockWidget_, glyphDetails_);
|
242 | 242 | comparatorTab_ = new ComperatorTab(this, engine_);
|
243 | + infoTab_ = new InfoTab(this, engine_);
|
|
243 | 244 | |
244 | 245 | tabWidget_ = new QTabWidget(this);
|
245 | 246 | |
... | ... | @@ -250,6 +251,8 @@ MainGUI::createLayout() |
250 | 251 | tabWidget_->addTab(continuousTab_, tr("Continuous View"));
|
251 | 252 | tabs_.append(comparatorTab_);
|
252 | 253 | tabWidget_->addTab(comparatorTab_, tr("Comparator View"));
|
254 | + tabs_.append(infoTab_);
|
|
255 | + tabWidget_->addTab(infoTab_, tr("Font Info"));
|
|
253 | 256 |
|
254 | 257 | tripletSelector_ = new TripletSelector(this, engine_);
|
255 | 258 |
... | ... | @@ -11,6 +11,7 @@ |
11 | 11 | #include "panels/singular.hpp"
|
12 | 12 | #include "panels/continuous.hpp"
|
13 | 13 | #include "panels/comparator.hpp"
|
14 | +#include "panels/info.hpp"
|
|
14 | 15 | #include "panels/glyphdetails.hpp"
|
15 | 16 | |
16 | 17 | #include <QAction>
|
... | ... | @@ -112,6 +113,7 @@ private: |
112 | 113 | SingularTab* singularTab_;
|
113 | 114 | ContinuousTab* continuousTab_;
|
114 | 115 | ComperatorTab* comparatorTab_;
|
116 | + InfoTab* infoTab_;
|
|
115 | 117 | |
116 | 118 | QDockWidget* glyphDetailsDockWidget_;
|
117 | 119 | GlyphDetails* glyphDetails_;
|
... | ... | @@ -26,6 +26,7 @@ if qt5_dep.found() |
26 | 26 | 'engine/charmap.cpp',
|
27 | 27 | 'engine/paletteinfo.cpp',
|
28 | 28 | 'engine/stringrenderer.cpp',
|
29 | + 'engine/fontinfo.cpp',
|
|
29 | 30 | |
30 | 31 | 'rendering/glyphbitmap.cpp',
|
31 | 32 | 'rendering/glyphoutline.cpp',
|
... | ... | @@ -42,12 +43,14 @@ if qt5_dep.found() |
42 | 43 | 'widgets/charmapcombobox.cpp',
|
43 | 44 | |
44 | 45 | 'models/customcomboboxmodels.cpp',
|
46 | + 'models/fontinfomodels.cpp',
|
|
45 | 47 | |
46 | 48 | 'panels/settingpanel.cpp',
|
47 | 49 | 'panels/singular.cpp',
|
48 | 50 | 'panels/continuous.cpp',
|
49 | 51 | 'panels/comparator.cpp',
|
50 | 52 | 'panels/glyphdetails.cpp',
|
53 | + 'panels/info.cpp',
|
|
51 | 54 | |
52 | 55 | 'ftinspect.cpp',
|
53 | 56 | 'maingui.cpp',
|
... | ... | @@ -65,11 +68,13 @@ if qt5_dep.found() |
65 | 68 | 'rendering/glyphbitmap.hpp',
|
66 | 69 | 'rendering/glyphcontinuous.hpp',
|
67 | 70 | 'models/customcomboboxmodels.hpp',
|
71 | + 'models/fontinfomodels.hpp',
|
|
68 | 72 | 'panels/settingpanel.hpp',
|
69 | 73 | 'panels/singular.hpp',
|
70 | 74 | 'panels/continuous.hpp',
|
71 | 75 | 'panels/comparator.hpp',
|
72 | 76 | 'panels/glyphdetails.hpp',
|
77 | + 'panels/info.hpp',
|
|
73 | 78 | 'maingui.hpp',
|
74 | 79 | ],
|
75 | 80 | dependencies: qt5_dep)
|
1 | +// fontinfomodels.cpp
|
|
2 | + |
|
3 | +// Copyright (C) 2022 by Charlie Jiang.
|
|
4 | + |
|
5 | +#include "fontinfomodels.hpp"
|
|
6 | + |
|
7 | +int
|
|
8 | +FixedSizeInfoModel::rowCount(const QModelIndex& parent) const
|
|
9 | +{
|
|
10 | + if (parent.isValid())
|
|
11 | + return 0;
|
|
12 | + return static_cast<int>(storage_.size());
|
|
13 | +}
|
|
14 | + |
|
15 | + |
|
16 | +int
|
|
17 | +FixedSizeInfoModel::columnCount(const QModelIndex& parent) const
|
|
18 | +{
|
|
19 | + if (parent.isValid())
|
|
20 | + return 0;
|
|
21 | + return FSIM_Max;
|
|
22 | +}
|
|
23 | + |
|
24 | + |
|
25 | +QVariant
|
|
26 | +FixedSizeInfoModel::data(const QModelIndex& index,
|
|
27 | + int role) const
|
|
28 | +{
|
|
29 | + if (index.row() < 0 || index.column() < 0)
|
|
30 | + return {};
|
|
31 | + auto r = static_cast<size_t>(index.row());
|
|
32 | + if (role != Qt::DisplayRole || r > storage_.size())
|
|
33 | + return {};
|
|
34 | + |
|
35 | + auto& obj = storage_[r];
|
|
36 | + switch (static_cast<Columns>(index.column()))
|
|
37 | + {
|
|
38 | + case FSIM_Index:
|
|
39 | + return index.row();
|
|
40 | + case FSIM_Height:
|
|
41 | + return obj.height;
|
|
42 | + case FSIM_Width:
|
|
43 | + return obj.width;
|
|
44 | + case FSIM_Size:
|
|
45 | + return obj.size;
|
|
46 | + case FSIM_XPpem:
|
|
47 | + return obj.xPpem;
|
|
48 | + case FSIM_YPpem:
|
|
49 | + return obj.yPpem;
|
|
50 | + }
|
|
51 | + |
|
52 | + return {};
|
|
53 | +}
|
|
54 | + |
|
55 | + |
|
56 | +QVariant
|
|
57 | +FixedSizeInfoModel::headerData(int section,
|
|
58 | + Qt::Orientation orientation,
|
|
59 | + int role) const
|
|
60 | +{
|
|
61 | + if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
|
|
62 | + return {};
|
|
63 | + |
|
64 | + switch (static_cast<Columns>(section))
|
|
65 | + {
|
|
66 | + case FSIM_Index:
|
|
67 | + return tr("#");
|
|
68 | + case FSIM_Height:
|
|
69 | + return tr("Height");
|
|
70 | + case FSIM_Width:
|
|
71 | + return tr("Width");
|
|
72 | + case FSIM_Size:
|
|
73 | + return tr("Size");
|
|
74 | + case FSIM_XPpem:
|
|
75 | + return tr("X ppem");
|
|
76 | + case FSIM_YPpem:
|
|
77 | + return tr("Y ppem");
|
|
78 | + }
|
|
79 | + |
|
80 | + return {};
|
|
81 | +}
|
|
82 | + |
|
83 | + |
|
84 | +int
|
|
85 | +CharMapInfoModel::rowCount(const QModelIndex& parent) const
|
|
86 | +{
|
|
87 | + if (parent.isValid())
|
|
88 | + return 0;
|
|
89 | + return static_cast<int>(storage_.size());
|
|
90 | +}
|
|
91 | + |
|
92 | + |
|
93 | +int
|
|
94 | +CharMapInfoModel::columnCount(const QModelIndex& parent) const
|
|
95 | +{
|
|
96 | + if (parent.isValid())
|
|
97 | + return 0;
|
|
98 | + return CMIM_Max;
|
|
99 | +}
|
|
100 | + |
|
101 | + |
|
102 | +QVariant
|
|
103 | +CharMapInfoModel::data(const QModelIndex& index,
|
|
104 | + int role) const
|
|
105 | +{
|
|
106 | + // TODO reduce duplication
|
|
107 | + if (index.row() < 0 || index.column() < 0)
|
|
108 | + return {};
|
|
109 | + auto r = static_cast<size_t>(index.row());
|
|
110 | + if (role != Qt::DisplayRole || r > storage_.size())
|
|
111 | + return {};
|
|
112 | + |
|
113 | + auto& obj = storage_[r];
|
|
114 | + switch (static_cast<Columns>(index.column()))
|
|
115 | + {
|
|
116 | + case CMIM_Index:
|
|
117 | + return index.row();
|
|
118 | + case CMIM_Encoding:
|
|
119 | + return *obj.encodingName;
|
|
120 | + case CMIM_PlatformID:
|
|
121 | + return obj.platformID;
|
|
122 | + case CMIM_EncodingID:
|
|
123 | + return obj.encodingID;
|
|
124 | + case CMIM_FormatID:
|
|
125 | + return obj.formatID;
|
|
126 | + case CMIM_LanguageID:
|
|
127 | + return static_cast<unsigned long long>(obj.languageID);
|
|
128 | + case CMIM_MaxIndex:
|
|
129 | + return obj.maxIndex;
|
|
130 | + }
|
|
131 | + |
|
132 | + return {};
|
|
133 | +}
|
|
134 | + |
|
135 | + |
|
136 | +QVariant
|
|
137 | +CharMapInfoModel::headerData(int section,
|
|
138 | + Qt::Orientation orientation,
|
|
139 | + int role) const
|
|
140 | +{
|
|
141 | + if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
|
|
142 | + return {};
|
|
143 | + |
|
144 | + switch (static_cast<Columns>(section))
|
|
145 | + {
|
|
146 | + case CMIM_Index:
|
|
147 | + return "#";
|
|
148 | + case CMIM_Encoding:
|
|
149 | + return "Encoding";
|
|
150 | + case CMIM_PlatformID:
|
|
151 | + return "Platform ID";
|
|
152 | + case CMIM_EncodingID:
|
|
153 | + return "Encoding ID";
|
|
154 | + case CMIM_FormatID:
|
|
155 | + return "Format ID";
|
|
156 | + case CMIM_LanguageID:
|
|
157 | + return "Language ID";
|
|
158 | + case CMIM_MaxIndex:
|
|
159 | + return "Max Code Point";
|
|
160 | + }
|
|
161 | + |
|
162 | + return {};
|
|
163 | +}
|
|
164 | + |
|
165 | + |
|
166 | +// end of fontinfomodels.cpp |
1 | +// fontinfomodels.hpp
|
|
2 | + |
|
3 | +// Copyright (C) 2022 by Charlie Jiang.
|
|
4 | + |
|
5 | +#pragma once
|
|
6 | + |
|
7 | +#include "../engine/fontinfo.hpp"
|
|
8 | +#include "../engine/charmap.hpp"
|
|
9 | + |
|
10 | +#include <vector>
|
|
11 | +#include <QAbstractTableModel>
|
|
12 | + |
|
13 | +class FixedSizeInfoModel
|
|
14 | +: public QAbstractTableModel
|
|
15 | +{
|
|
16 | + Q_OBJECT
|
|
17 | +public:
|
|
18 | + explicit FixedSizeInfoModel(QObject* parent) : QAbstractTableModel(parent) {}
|
|
19 | + ~FixedSizeInfoModel() override = default;
|
|
20 | + |
|
21 | + int rowCount(const QModelIndex& parent) const override;
|
|
22 | + int columnCount(const QModelIndex& parent) const override;
|
|
23 | + QVariant data(const QModelIndex& index,
|
|
24 | + int role) const override;
|
|
25 | + QVariant headerData(int section,
|
|
26 | + Qt::Orientation orientation,
|
|
27 | + int role) const override;
|
|
28 | + |
|
29 | + // Since we need to call `beginResetModel` right before updating, and need to
|
|
30 | + // call `endResetModel` after the internal storage is changed
|
|
31 | + // The model should be updated on-demand, and the internal storage is updated
|
|
32 | + // from `FontFixedSize::get`, we provide a callback for `get` to ensure the
|
|
33 | + // `beginResetModel` is called before the storage is changed,
|
|
34 | + // and the caller is responsible to call `endResetModel` according to `get`'s
|
|
35 | + // return value.
|
|
36 | + void beginModelUpdate() { beginResetModel(); }
|
|
37 | + void endModelUpdate() { endResetModel(); }
|
|
38 | + std::vector<FontFixedSize>& storage() { return storage_; }
|
|
39 | + |
|
40 | + enum Columns : int
|
|
41 | + {
|
|
42 | + FSIM_Index = 0,
|
|
43 | + FSIM_Height = 1,
|
|
44 | + FSIM_Width = 2,
|
|
45 | + FSIM_Size = 3,
|
|
46 | + FSIM_XPpem = 4,
|
|
47 | + FSIM_YPpem = 5,
|
|
48 | + FSIM_Max
|
|
49 | + };
|
|
50 | + |
|
51 | +private:
|
|
52 | + // Don't let the item count exceed INT_MAX!
|
|
53 | + std::vector<FontFixedSize> storage_;
|
|
54 | +};
|
|
55 | + |
|
56 | + |
|
57 | +class CharMapInfoModel
|
|
58 | +: public QAbstractTableModel
|
|
59 | +{
|
|
60 | + Q_OBJECT
|
|
61 | +public:
|
|
62 | + explicit CharMapInfoModel(QObject* parent) : QAbstractTableModel(parent) {}
|
|
63 | + ~CharMapInfoModel() override = default;
|
|
64 | + |
|
65 | + int rowCount(const QModelIndex& parent) const override;
|
|
66 | + int columnCount(const QModelIndex& parent) const override;
|
|
67 | + QVariant data(const QModelIndex& index,
|
|
68 | + int role) const override;
|
|
69 | + QVariant headerData(int section,
|
|
70 | + Qt::Orientation orientation,
|
|
71 | + int role) const override;
|
|
72 | + |
|
73 | + // Same to `FixedSizeInfoModel`
|
|
74 | + void beginModelUpdate() { beginResetModel(); }
|
|
75 | + void endModelUpdate() { endResetModel(); }
|
|
76 | + std::vector<CharMapInfo>& storage() { return storage_; }
|
|
77 | + |
|
78 | + enum Columns : int
|
|
79 | + {
|
|
80 | + CMIM_Index = 0,
|
|
81 | + CMIM_Encoding = 1,
|
|
82 | + CMIM_PlatformID = 2,
|
|
83 | + CMIM_EncodingID = 3,
|
|
84 | + CMIM_FormatID = 4,
|
|
85 | + CMIM_LanguageID = 5,
|
|
86 | + CMIM_MaxIndex = 6,
|
|
87 | + CMIM_Max
|
|
88 | + };
|
|
89 | + |
|
90 | +private:
|
|
91 | + // Don't let the item count exceed INT_MAX!
|
|
92 | + std::vector<CharMapInfo> storage_;
|
|
93 | +};
|
|
94 | + |
|
95 | + |
|
96 | +// end of fontinfomodels.hpp |
1 | +// info.cpp
|
|
2 | + |
|
3 | +// Copyright (C) 2022 by Charlie Jiang.
|
|
4 | + |
|
5 | +#include "info.hpp"
|
|
6 | + |
|
7 | +#include "../uihelper.hpp"
|
|
8 | +#include "../engine/engine.hpp"
|
|
9 | + |
|
10 | +#include <QStringList>
|
|
11 | +#include <QHeaderView>
|
|
12 | + |
|
13 | +InfoTab::InfoTab(QWidget* parent,
|
|
14 | + Engine* engine)
|
|
15 | +: QWidget(parent), engine_(engine)
|
|
16 | +{
|
|
17 | + createLayout();
|
|
18 | +}
|
|
19 | + |
|
20 | + |
|
21 | +void
|
|
22 | +InfoTab::reloadFont()
|
|
23 | +{
|
|
24 | + for (auto tab : tabs_)
|
|
25 | + tab->reloadFont();
|
|
26 | +}
|
|
27 | + |
|
28 | + |
|
29 | +void
|
|
30 | +InfoTab::createLayout()
|
|
31 | +{
|
|
32 | + generalTab_ = new GeneralInfoTab(this, engine_);
|
|
33 | + sfntTab_ = new SFNTInfoTab(this, engine_);
|
|
34 | + postScriptTab_ = new PostScriptInfoTab(this, engine_);
|
|
35 | + mmgxTab_ = new MMGXInfoTab(this, engine_);
|
|
36 | + |
|
37 | + tab_ = new QTabWidget(this);
|
|
38 | + tab_->addTab(generalTab_, tr("General"));
|
|
39 | + tab_->addTab(sfntTab_, tr("SFNT"));
|
|
40 | + tab_->addTab(postScriptTab_, tr("PostScript"));
|
|
41 | + tab_->addTab(mmgxTab_, tr("MM/GX"));
|
|
42 | + |
|
43 | + tabs_.append(generalTab_);
|
|
44 | + tabs_.append(sfntTab_);
|
|
45 | + tabs_.append(postScriptTab_);
|
|
46 | + tabs_.append(mmgxTab_);
|
|
47 | + |
|
48 | + layout_ = new QHBoxLayout;
|
|
49 | + layout_->addWidget(tab_);
|
|
50 | + |
|
51 | + setLayout(layout_);
|
|
52 | +}
|
|
53 | + |
|
54 | + |
|
55 | +GeneralInfoTab::GeneralInfoTab(QWidget* parent,
|
|
56 | + Engine* engine)
|
|
57 | +: QWidget(parent), engine_(engine)
|
|
58 | +{
|
|
59 | + createLayout();
|
|
60 | +}
|
|
61 | + |
|
62 | + |
|
63 | +void
|
|
64 | +GeneralInfoTab::reloadFont()
|
|
65 | +{
|
|
66 | + auto basicInfo = FontBasicInfo::get(engine_);
|
|
67 | + // don't update when unnecessary
|
|
68 | + if (basicInfo != oldFontBasicInfo_)
|
|
69 | + {
|
|
70 | + oldFontBasicInfo_ = basicInfo;
|
|
71 | + if (basicInfo.numFaces < 0)
|
|
72 | + numFacesLabel_->clear();
|
|
73 | + else
|
|
74 | + numFacesLabel_->setText(QString::number(basicInfo.numFaces));
|
|
75 | +
|
|
76 | + familyLabel_->setText(basicInfo.familyName);
|
|
77 | + styleLabel_->setText(basicInfo.styleName);
|
|
78 | + postscriptLabel_->setText(basicInfo.postscriptName);
|
|
79 | + revisionLabel_->setText(basicInfo.revision);
|
|
80 | + copyrightLabel_->setText(basicInfo.copyright);
|
|
81 | + trademarkLabel_->setText(basicInfo.trademark);
|
|
82 | + manufacturerLabel_->setText(basicInfo.manufacturer);
|
|
83 | +
|
|
84 | + createdLabel_->setText(
|
|
85 | + basicInfo.createdTime.toString("yyyy-MM-dd hh:mm:ss t"));
|
|
86 | + modifiedLabel_->setText(
|
|
87 | + basicInfo.modifiedTime.toString("yyyy-MM-dd hh:mm:ss t"));
|
|
88 | + }
|
|
89 | + |
|
90 | + auto fontTypeEntries = FontTypeEntries::get(engine_);
|
|
91 | + |
|
92 | + if (fontTypeEntries != oldFontTypeEntries_)
|
|
93 | + {
|
|
94 | + oldFontTypeEntries_ = fontTypeEntries;
|
|
95 | + QString directionText;
|
|
96 | + // Don't want to do concat...
|
|
97 | + if (fontTypeEntries.hasHorizontal && fontTypeEntries.hasVertical)
|
|
98 | + directionText = "honizontal, vertical";
|
|
99 | + else if (fontTypeEntries.hasHorizontal)
|
|
100 | + directionText = "horizontal";
|
|
101 | + else if (fontTypeEntries.hasVertical)
|
|
102 | + directionText = "vertical";
|
|
103 | +
|
|
104 | + QStringList types;
|
|
105 | + if (fontTypeEntries.scalable)
|
|
106 | + types += "scalable";
|
|
107 | + if (fontTypeEntries.mmgx)
|
|
108 | + types += "multiple master";
|
|
109 | + if (fontTypeEntries.fixedSizes)
|
|
110 | + types += "fixed sizes";
|
|
111 | +
|
|
112 | + driverNameLabel_->setText(fontTypeEntries.driverName);
|
|
113 | + sfntLabel_->setText(fontTypeEntries.sfnt ? "yes" : "no");
|
|
114 | + fontTypeLabel_->setText(types.join(", "));
|
|
115 | + directionLabel_->setText(directionText);
|
|
116 | + fixedWidthLabel_->setText(fontTypeEntries.fixedWidth ? "yes" : "no");
|
|
117 | + glyphNamesLabel_->setText(fontTypeEntries.glyphNames ? "available"
|
|
118 | + : "unavailable");
|
|
119 | + |
|
120 | + if (fontTypeEntries.scalable)
|
|
121 | + {
|
|
122 | + emSizeLabel_->setText(QString::number(fontTypeEntries.emSize));
|
|
123 | + bboxLabel_->setText(QString("(%1, %2) : (%3, %4)")
|
|
124 | + .arg(fontTypeEntries.globalBBox.xMin)
|
|
125 | + .arg(fontTypeEntries.globalBBox.yMin)
|
|
126 | + .arg(fontTypeEntries.globalBBox.xMax)
|
|
127 | + .arg(fontTypeEntries.globalBBox.yMax));
|
|
128 | + ascenderLabel_->setText(QString::number(fontTypeEntries.ascender));
|
|
129 | + descenderLabel_->setText(QString::number(fontTypeEntries.descender));
|
|
130 | + maxAdvanceWidthLabel_
|
|
131 | + ->setText(QString::number(fontTypeEntries.maxAdvanceWidth));
|
|
132 | + maxAdvanceHeightLabel_
|
|
133 | + ->setText(QString::number(fontTypeEntries.maxAdvanceHeight));
|
|
134 | + ulPosLabel_
|
|
135 | + ->setText(QString::number(fontTypeEntries.underlinePos));
|
|
136 | + ulThicknessLabel_
|
|
137 | + ->setText(QString::number(fontTypeEntries.underlineThickness));
|
|
138 | + |
|
139 | + for (auto label : scalableOnlyLabels_)
|
|
140 | + label->setEnabled(true);
|
|
141 | + }
|
|
142 | + else
|
|
143 | + {
|
|
144 | + for (auto label : scalableOnlyLabels_)
|
|
145 | + label->setEnabled(false);
|
|
146 | + }
|
|
147 | + }
|
|
148 | + |
|
149 | + fixedSizesTable_->setEnabled(fontTypeEntries.fixedSizes);
|
|
150 | + bool reset
|
|
151 | + = FontFixedSize::get(engine_,
|
|
152 | + fixedSizeInfoModel_->storage(),
|
|
153 | + [&] { fixedSizeInfoModel_->beginModelUpdate(); });
|
|
154 | + if (reset)
|
|
155 | + fixedSizeInfoModel_->endModelUpdate();
|
|
156 | + |
|
157 | + if (engine_->currentFontCharMaps() != charMapInfoModel_->storage())
|
|
158 | + {
|
|
159 | + charMapInfoModel_->beginModelUpdate();
|
|
160 | + charMapInfoModel_->storage() = engine_->currentFontCharMaps();
|
|
161 | + charMapInfoModel_->endModelUpdate();
|
|
162 | + }
|
|
163 | +}
|
|
164 | + |
|
165 | + |
|
166 | +void
|
|
167 | +GeneralInfoTab::createLayout()
|
|
168 | +{
|
|
169 | + numFacesPromptLabel_ = new QLabel(tr("Num of Faces:"), this);
|
|
170 | + familyPromptLabel_ = new QLabel(tr("Family Name:"), this);
|
|
171 | + stylePromptLabel_ = new QLabel(tr("Style Name:"), this);
|
|
172 | + postscriptPromptLabel_ = new QLabel(tr("PostScript Name:"), this);
|
|
173 | + createdPromptLabel_ = new QLabel(tr("Created at:"), this);
|
|
174 | + modifiedPromptLabel_ = new QLabel(tr("Modified at:"), this);
|
|
175 | + revisionPromptLabel_ = new QLabel(tr("Font Revision:"), this);
|
|
176 | + copyrightPromptLabel_ = new QLabel(tr("Copyright:"), this);
|
|
177 | + trademarkPromptLabel_ = new QLabel(tr("Trademark:"), this);
|
|
178 | + manufacturerPromptLabel_ = new QLabel(tr("Manufacturer:"), this);
|
|
179 | + |
|
180 | + numFacesLabel_ = new QLabel(this);
|
|
181 | + familyLabel_ = new QLabel(this);
|
|
182 | + styleLabel_ = new QLabel(this);
|
|
183 | + postscriptLabel_ = new QLabel(this);
|
|
184 | + createdLabel_ = new QLabel(this);
|
|
185 | + modifiedLabel_ = new QLabel(this);
|
|
186 | + revisionLabel_ = new QLabel(this);
|
|
187 | + copyrightLabel_ = new QLabel(this);
|
|
188 | + trademarkLabel_ = new QLabel(this);
|
|
189 | + manufacturerLabel_ = new QLabel(this);
|
|
190 | + |
|
191 | + setLabelSelectable( numFacesLabel_);
|
|
192 | + setLabelSelectable( familyLabel_);
|
|
193 | + setLabelSelectable( styleLabel_);
|
|
194 | + setLabelSelectable( postscriptLabel_);
|
|
195 | + setLabelSelectable( createdLabel_);
|
|
196 | + setLabelSelectable( modifiedLabel_);
|
|
197 | + setLabelSelectable( revisionLabel_);
|
|
198 | + setLabelSelectable( copyrightLabel_);
|
|
199 | + setLabelSelectable( trademarkLabel_);
|
|
200 | + setLabelSelectable(manufacturerLabel_);
|
|
201 | + |
|
202 | + driverNamePromptLabel_ = new QLabel(tr("Driver:"), this);
|
|
203 | + sfntPromptLabel_ = new QLabel(tr("SFNT Wrapped:"), this);
|
|
204 | + fontTypePromptLabel_ = new QLabel(tr("Type:"), this);
|
|
205 | + directionPromptLabel_ = new QLabel(tr("Direction:"), this);
|
|
206 | + fixedWidthPromptLabel_ = new QLabel(tr("Fixed Width:"), this);
|
|
207 | + glyphNamesPromptLabel_ = new QLabel(tr("Glyph Names:"), this);
|
|
208 | + |
|
209 | + driverNameLabel_ = new QLabel(this);
|
|
210 | + sfntLabel_ = new QLabel(this);
|
|
211 | + fontTypeLabel_ = new QLabel(this);
|
|
212 | + directionLabel_ = new QLabel(this);
|
|
213 | + fixedWidthLabel_ = new QLabel(this);
|
|
214 | + glyphNamesLabel_ = new QLabel(this);
|
|
215 | + |
|
216 | + setLabelSelectable(driverNameLabel_);
|
|
217 | + setLabelSelectable( sfntLabel_);
|
|
218 | + setLabelSelectable( fontTypeLabel_);
|
|
219 | + setLabelSelectable( directionLabel_);
|
|
220 | + setLabelSelectable(fixedWidthLabel_);
|
|
221 | + setLabelSelectable(glyphNamesLabel_);
|
|
222 | + |
|
223 | + emSizePromptLabel_ = new QLabel(tr("EM Size:"), this);
|
|
224 | + bboxPromptLabel_ = new QLabel(tr("Global BBox:"), this);
|
|
225 | + ascenderPromptLabel_ = new QLabel(tr("Ascender:"), this);
|
|
226 | + descenderPromptLabel_ = new QLabel(tr("Descender:"), this);
|
|
227 | + maxAdvanceWidthPromptLabel_ = new QLabel(tr("Max Advance Width:"), this);
|
|
228 | + maxAdvanceHeightPromptLabel_ = new QLabel(tr("Max Advance Height:"), this);
|
|
229 | + ulPosPromptLabel_ = new QLabel(tr("Underline Position:"), this);
|
|
230 | + ulThicknessPromptLabel_ = new QLabel(tr("Underline Thickness:"), this);
|
|
231 | + |
|
232 | + emSizeLabel_ = new QLabel(this);
|
|
233 | + bboxLabel_ = new QLabel(this);
|
|
234 | + ascenderLabel_ = new QLabel(this);
|
|
235 | + descenderLabel_ = new QLabel(this);
|
|
236 | + maxAdvanceWidthLabel_ = new QLabel(this);
|
|
237 | + maxAdvanceHeightLabel_ = new QLabel(this);
|
|
238 | + ulPosLabel_ = new QLabel(this);
|
|
239 | + ulThicknessLabel_ = new QLabel(this);
|
|
240 | + |
|
241 | + setLabelSelectable( emSizeLabel_);
|
|
242 | + setLabelSelectable( bboxLabel_);
|
|
243 | + setLabelSelectable( ascenderLabel_);
|
|
244 | + setLabelSelectable( descenderLabel_);
|
|
245 | + setLabelSelectable( maxAdvanceWidthLabel_);
|
|
246 | + setLabelSelectable(maxAdvanceHeightLabel_);
|
|
247 | + setLabelSelectable( ulPosLabel_);
|
|
248 | + setLabelSelectable( ulThicknessLabel_);
|
|
249 | + |
|
250 | + scalableOnlyLabels_.push_back( emSizePromptLabel_);
|
|
251 | + scalableOnlyLabels_.push_back( bboxPromptLabel_);
|
|
252 | + scalableOnlyLabels_.push_back( ascenderPromptLabel_);
|
|
253 | + scalableOnlyLabels_.push_back( descenderPromptLabel_);
|
|
254 | + scalableOnlyLabels_.push_back( maxAdvanceWidthPromptLabel_);
|
|
255 | + scalableOnlyLabels_.push_back(maxAdvanceHeightPromptLabel_);
|
|
256 | + scalableOnlyLabels_.push_back( ulPosPromptLabel_);
|
|
257 | + scalableOnlyLabels_.push_back( ulThicknessPromptLabel_);
|
|
258 | + scalableOnlyLabels_.push_back( emSizeLabel_);
|
|
259 | + scalableOnlyLabels_.push_back( bboxLabel_);
|
|
260 | + scalableOnlyLabels_.push_back( ascenderLabel_);
|
|
261 | + scalableOnlyLabels_.push_back( descenderLabel_);
|
|
262 | + scalableOnlyLabels_.push_back( maxAdvanceWidthLabel_);
|
|
263 | + scalableOnlyLabels_.push_back(maxAdvanceHeightLabel_);
|
|
264 | + scalableOnlyLabels_.push_back( ulPosLabel_);
|
|
265 | + scalableOnlyLabels_.push_back( ulThicknessLabel_);
|
|
266 | + |
|
267 | + basicGroupBox_ = new QGroupBox(tr("Basic"), this);
|
|
268 | + typeEntriesGroupBox_ = new QGroupBox(tr("Type Entries"), this);
|
|
269 | + charMapGroupBox_ = new QGroupBox(tr("CharMaps"), this);
|
|
270 | + fixedSizesGroupBox_ = new QGroupBox(tr("Fixed Sizes"), this);
|
|
271 | + |
|
272 | + charMapsTable_ = new QTableView(this);
|
|
273 | + fixedSizesTable_ = new QTableView(this);
|
|
274 | + |
|
275 | + charMapInfoModel_ = new CharMapInfoModel(this);
|
|
276 | + charMapsTable_->setModel(charMapInfoModel_);
|
|
277 | + auto header = charMapsTable_->verticalHeader();
|
|
278 | + // This will force the minimal size to be used
|
|
279 | + header->setDefaultSectionSize(0);
|
|
280 | + header->setSectionResizeMode(QHeaderView::Fixed);
|
|
281 | + |
|
282 | + fixedSizeInfoModel_ = new FixedSizeInfoModel(this);
|
|
283 | + fixedSizesTable_->setModel(fixedSizeInfoModel_);
|
|
284 | + header = fixedSizesTable_->verticalHeader();
|
|
285 | + header->setDefaultSectionSize(0);
|
|
286 | + header->setSectionResizeMode(QHeaderView::Fixed);
|
|
287 | + |
|
288 | + basicLayout_ = new QGridLayout;
|
|
289 | + typeEntriesLayout_ = new QGridLayout;
|
|
290 | + charMapLayout_ = new QHBoxLayout;
|
|
291 | + fixedSizesLayout_ = new QHBoxLayout;
|
|
292 | + |
|
293 | +#define GL2CRow(l, w) gridLayout2ColAddWidget(l , \
|
|
294 | + w##PromptLabel_, \
|
|
295 | + w##Label_)
|
|
296 | +#define BasicRow(w) GL2CRow(basicLayout_, w)
|
|
297 | +#define FTERow(w) GL2CRow(typeEntriesLayout_, w)
|
|
298 | + |
|
299 | + BasicRow( numFaces);
|
|
300 | + BasicRow( family);
|
|
301 | + BasicRow( style);
|
|
302 | + BasicRow( postscript);
|
|
303 | + BasicRow( created);
|
|
304 | + BasicRow( modified);
|
|
305 | + BasicRow( revision);
|
|
306 | + BasicRow( copyright);
|
|
307 | + BasicRow( trademark);
|
|
308 | + BasicRow(manufacturer);
|
|
309 | + |
|
310 | + FTERow( driverName);
|
|
311 | + FTERow( sfnt);
|
|
312 | + FTERow( fontType);
|
|
313 | + FTERow( direction);
|
|
314 | + FTERow( fixedWidth);
|
|
315 | + FTERow( glyphNames);
|
|
316 | + FTERow( emSize);
|
|
317 | + FTERow( bbox);
|
|
318 | + FTERow( ascender);
|
|
319 | + FTERow( descender);
|
|
320 | + FTERow( maxAdvanceWidth);
|
|
321 | + FTERow(maxAdvanceHeight);
|
|
322 | + FTERow( ulPos);
|
|
323 | + FTERow( ulThickness);
|
|
324 | + |
|
325 | + charMapLayout_->addWidget(charMapsTable_);
|
|
326 | + fixedSizesLayout_->addWidget(fixedSizesTable_);
|
|
327 | + |
|
328 | + basicGroupBox_ ->setLayout(basicLayout_ );
|
|
329 | + typeEntriesGroupBox_ ->setLayout(typeEntriesLayout_);
|
|
330 | + charMapGroupBox_ ->setLayout(charMapLayout_ );
|
|
331 | + fixedSizesGroupBox_ ->setLayout(fixedSizesLayout_ );
|
|
332 | + |
|
333 | + leftLayout_ = new QVBoxLayout;
|
|
334 | + rightLayout_ = new QVBoxLayout;
|
|
335 | + mainLayout_ = new QHBoxLayout;
|
|
336 | + |
|
337 | + leftLayout_->addWidget(basicGroupBox_);
|
|
338 | + leftLayout_->addWidget(typeEntriesGroupBox_);
|
|
339 | + leftLayout_->addSpacerItem(new QSpacerItem(0, 0,
|
|
340 | + QSizePolicy::Preferred,
|
|
341 | + QSizePolicy::Expanding));
|
|
342 | + |
|
343 | + rightLayout_->addWidget(charMapGroupBox_);
|
|
344 | + rightLayout_->addWidget(fixedSizesGroupBox_);
|
|
345 | + |
|
346 | + mainLayout_->addLayout(leftLayout_);
|
|
347 | + mainLayout_->addLayout(rightLayout_);
|
|
348 | + setLayout(mainLayout_);
|
|
349 | +}
|
|
350 | + |
|
351 | + |
|
352 | +SFNTInfoTab::SFNTInfoTab(QWidget* parent,
|
|
353 | + Engine* engine)
|
|
354 | +: QWidget(parent), engine_(engine)
|
|
355 | +{
|
|
356 | +}
|
|
357 | + |
|
358 | + |
|
359 | +void
|
|
360 | +SFNTInfoTab::reloadFont()
|
|
361 | +{
|
|
362 | +}
|
|
363 | + |
|
364 | + |
|
365 | +PostScriptInfoTab::PostScriptInfoTab(QWidget* parent,
|
|
366 | + Engine* engine)
|
|
367 | +: QWidget(parent), engine_(engine)
|
|
368 | +{
|
|
369 | +}
|
|
370 | + |
|
371 | + |
|
372 | +void
|
|
373 | +PostScriptInfoTab::reloadFont()
|
|
374 | +{
|
|
375 | +}
|
|
376 | + |
|
377 | + |
|
378 | +MMGXInfoTab::MMGXInfoTab(QWidget* parent,
|
|
379 | + Engine* engine)
|
|
380 | +: QWidget(parent), engine_(engine)
|
|
381 | +{
|
|
382 | +}
|
|
383 | + |
|
384 | + |
|
385 | +void
|
|
386 | +MMGXInfoTab::reloadFont()
|
|
387 | +{
|
|
388 | +}
|
|
389 | + |
|
390 | + |
|
391 | +// end of info.cpp |
1 | +// info.hpp
|
|
2 | + |
|
3 | +// Copyright (C) 2022 by Charlie Jiang.
|
|
4 | + |
|
5 | +#pragma once
|
|
6 | + |
|
7 | +#include "abstracttab.hpp"
|
|
8 | +#include "../engine/fontinfo.hpp"
|
|
9 | +#include "../models/fontinfomodels.hpp"
|
|
10 | + |
|
11 | +#include <vector>
|
|
12 | +#include <QWidget>
|
|
13 | +#include <QTabWidget>
|
|
14 | +#include <QBoxLayout>
|
|
15 | +#include <QGridLayout>
|
|
16 | +#include <QVector>
|
|
17 | +#include <QLabel>
|
|
18 | +#include <QGroupBox>
|
|
19 | +#include <QTableView>
|
|
20 | +#include <QStackedLayout>
|
|
21 | + |
|
22 | +class Engine;
|
|
23 | +class GeneralInfoTab;
|
|
24 | +class SFNTInfoTab;
|
|
25 | +class PostScriptInfoTab;
|
|
26 | +class MMGXInfoTab;
|
|
27 | + |
|
28 | +class InfoTab
|
|
29 | +: public QWidget, public AbstractTab
|
|
30 | +{
|
|
31 | + Q_OBJECT
|
|
32 | +public:
|
|
33 | + InfoTab(QWidget* parent, Engine* engine);
|
|
34 | + ~InfoTab() override = default;
|
|
35 | + |
|
36 | + void repaintGlyph() override {}
|
|
37 | + void reloadFont() override;
|
|
38 | + |
|
39 | +private:
|
|
40 | + Engine* engine_;
|
|
41 | + |
|
42 | + QVector<AbstractTab*> tabs_;
|
|
43 | + GeneralInfoTab* generalTab_;
|
|
44 | + SFNTInfoTab* sfntTab_;
|
|
45 | + PostScriptInfoTab* postScriptTab_;
|
|
46 | + MMGXInfoTab* mmgxTab_;
|
|
47 | + |
|
48 | + QTabWidget* tab_;
|
|
49 | + QHBoxLayout* layout_;
|
|
50 | + |
|
51 | + void createLayout();
|
|
52 | +};
|
|
53 | + |
|
54 | + |
|
55 | +class GeneralInfoTab
|
|
56 | +: public QWidget, public AbstractTab
|
|
57 | +{
|
|
58 | + Q_OBJECT
|
|
59 | +public:
|
|
60 | + GeneralInfoTab(QWidget* parent, Engine* engine);
|
|
61 | + ~GeneralInfoTab() override = default;
|
|
62 | + |
|
63 | + void repaintGlyph() override {}
|
|
64 | + void reloadFont() override;
|
|
65 | + |
|
66 | +private:
|
|
67 | + Engine* engine_;
|
|
68 | + |
|
69 | +#define LabelPair(name) \
|
|
70 | + QLabel* name##Label_; \
|
|
71 | + QLabel* name##PromptLabel_;
|
|
72 | + |
|
73 | + LabelPair( numFaces)
|
|
74 | + LabelPair( family)
|
|
75 | + LabelPair( style)
|
|
76 | + LabelPair( postscript)
|
|
77 | + LabelPair( created)
|
|
78 | + LabelPair( modified)
|
|
79 | + LabelPair( revision)
|
|
80 | + LabelPair( copyright)
|
|
81 | + LabelPair( trademark)
|
|
82 | + LabelPair(manufacturer)
|
|
83 | + |
|
84 | + LabelPair(driverName)
|
|
85 | + LabelPair( sfnt)
|
|
86 | + LabelPair( fontType)
|
|
87 | + LabelPair( direction)
|
|
88 | + LabelPair(fixedWidth)
|
|
89 | + LabelPair(glyphNames)
|
|
90 | + |
|
91 | + LabelPair( emSize)
|
|
92 | + LabelPair( bbox)
|
|
93 | + LabelPair( ascender)
|
|
94 | + LabelPair( descender)
|
|
95 | + LabelPair( maxAdvanceWidth)
|
|
96 | + LabelPair(maxAdvanceHeight)
|
|
97 | + LabelPair( ulPos)
|
|
98 | + LabelPair( ulThickness)
|
|
99 | + |
|
100 | + QGroupBox* basicGroupBox_;
|
|
101 | + QGroupBox* typeEntriesGroupBox_;
|
|
102 | + QGroupBox* charMapGroupBox_;
|
|
103 | + QGroupBox* fixedSizesGroupBox_;
|
|
104 | + |
|
105 | + QTableView* charMapsTable_;
|
|
106 | + QTableView* fixedSizesTable_;
|
|
107 | + |
|
108 | + FixedSizeInfoModel* fixedSizeInfoModel_;
|
|
109 | + CharMapInfoModel* charMapInfoModel_;
|
|
110 | + |
|
111 | + QHBoxLayout* mainLayout_;
|
|
112 | + QVBoxLayout* leftLayout_;
|
|
113 | + QVBoxLayout* rightLayout_;
|
|
114 | + QGridLayout* basicLayout_;
|
|
115 | + QGridLayout* typeEntriesLayout_;
|
|
116 | + QHBoxLayout* charMapLayout_;
|
|
117 | + QHBoxLayout* fixedSizesLayout_;
|
|
118 | + |
|
119 | + std::vector<QLabel*> scalableOnlyLabels_;
|
|
120 | + |
|
121 | + FontBasicInfo oldFontBasicInfo_ = {};
|
|
122 | + FontTypeEntries oldFontTypeEntries_ = {};
|
|
123 | + |
|
124 | + void createLayout();
|
|
125 | +};
|
|
126 | + |
|
127 | + |
|
128 | +class SFNTInfoTab
|
|
129 | +: public QWidget, public AbstractTab
|
|
130 | +{
|
|
131 | + Q_OBJECT
|
|
132 | +public:
|
|
133 | + SFNTInfoTab(QWidget* parent, Engine* engine);
|
|
134 | + ~SFNTInfoTab() override = default;
|
|
135 | + |
|
136 | + void repaintGlyph() override {}
|
|
137 | + void reloadFont() override;
|
|
138 | + |
|
139 | +private:
|
|
140 | + Engine* engine_;
|
|
141 | +};
|
|
142 | + |
|
143 | + |
|
144 | +class PostScriptInfoTab
|
|
145 | +: public QWidget, public AbstractTab
|
|
146 | +{
|
|
147 | + Q_OBJECT
|
|
148 | +public:
|
|
149 | + PostScriptInfoTab(QWidget* parent, Engine* engine);
|
|
150 | + ~PostScriptInfoTab() override = default;
|
|
151 | + |
|
152 | + void repaintGlyph() override {}
|
|
153 | + void reloadFont() override;
|
|
154 | + |
|
155 | +private:
|
|
156 | + Engine* engine_;
|
|
157 | +};
|
|
158 | + |
|
159 | + |
|
160 | +class MMGXInfoTab
|
|
161 | +: public QWidget, public AbstractTab
|
|
162 | +{
|
|
163 | + Q_OBJECT
|
|
164 | +public:
|
|
165 | + MMGXInfoTab(QWidget* parent, Engine* engine);
|
|
166 | + ~MMGXInfoTab() override = default;
|
|
167 | + |
|
168 | + void repaintGlyph() override {}
|
|
169 | + void reloadFont() override;
|
|
170 | + |
|
171 | +private:
|
|
172 | + Engine* engine_;
|
|
173 | +};
|
|
174 | + |
|
175 | + |
|
176 | +// end of info.hpp |