1414#include < mapbox/glyph_foundry_impl.hpp>
1515#include < utility>
1616
17+ // freetype2
18+ extern " C" {
19+ #include < ft2build.h>
20+ #include FT_TRUETYPE_TABLES_H
21+ }
22+
1723namespace node_fontnik {
1824
1925struct FaceMetadata {
@@ -26,17 +32,12 @@ struct FaceMetadata {
2632
2733 std::string family_name{};
2834 std::string style_name{};
35+ uint16_t weight{};
36+ float width{};
37+ bool italic{};
38+ float oblique{};
39+
2940 std::vector<int > points{};
30- FaceMetadata (std::string _family_name,
31- std::string _style_name,
32- std::vector<int >&& _points)
33- : family_name(std::move(_family_name)),
34- style_name (std::move(_style_name)),
35- points(std::move(_points)) {}
36- FaceMetadata (std::string _family_name,
37- std::vector<int >&& _points)
38- : family_name(std::move(_family_name)),
39- points(std::move(_points)) {}
4041};
4142
4243struct GlyphPBF {
@@ -88,6 +89,31 @@ struct ft_face_guard {
8889 FT_Face* face_;
8990};
9091
92+
93+ float getWidth (FT_UInt16 usWidthClass) {
94+ switch (usWidthClass) {
95+ case /* FWIDTH_ULTRA_CONDENSED */ 1 :
96+ return 50 .f ;
97+ case /* FWIDTH_EXTRA_CONDENSED */ 2 :
98+ return 62 .5f ;
99+ case /* FWIDTH_CONDENSED */ 3 :
100+ return 75 .f ;
101+ case /* FWIDTH_SEMI_CONDENSED */ 4 :
102+ return 87 .5f ;
103+ default :
104+ case /* FWIDTH_NORMAL */ 5 :
105+ return 100 .f ;
106+ case /* FWIDTH_SEMI_EXPANDED */ 6 :
107+ return 112 .5f ;
108+ case /* FWIDTH_EXPANDED */ 7 :
109+ return 125 .f ;
110+ case /* FWIDTH_EXTRA_EXPANDED */ 8 :
111+ return 150 .f ;
112+ case /* FWIDTH_ULTRA_EXPANDED */ 9 :
113+ return 200 .f ;
114+ }
115+ }
116+
91117struct AsyncLoad : Napi::AsyncWorker {
92118 using Base = Napi::AsyncWorker;
93119 AsyncLoad (Napi::Buffer<char > const & buffer, Napi::Function const & callback)
@@ -123,6 +149,11 @@ struct AsyncLoad : Napi::AsyncWorker {
123149 faces_.reserve (static_cast <std::size_t >(num_faces));
124150 }
125151 if (ft_face->family_name != nullptr ) {
152+ FaceMetadata metadata{ft_face->family_name };
153+ if (ft_face->style_name ) {
154+ metadata.style_name = ft_face->style_name ;
155+ }
156+
126157 std::set<int > points;
127158 FT_ULong charcode;
128159 FT_UInt gindex;
@@ -131,12 +162,43 @@ struct AsyncLoad : Napi::AsyncWorker {
131162 charcode = FT_Get_Next_Char (ft_face, charcode, &gindex);
132163 if (charcode != 0 ) points.emplace (charcode);
133164 }
134- std::vector<int > points_vec (points.begin (), points.end ());
135- if (ft_face->style_name != nullptr ) {
136- faces_.emplace_back (ft_face->family_name , ft_face->style_name , std::move (points_vec));
137- } else {
138- faces_.emplace_back (ft_face->family_name , std::move (points_vec));
165+ metadata.points = std::vector<int >(points.begin (), points.end ());
166+
167+ TT_Header* head = (TT_Header*)FT_Get_Sfnt_Table (ft_face, FT_SFNT_HEAD);
168+ TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table (ft_face, FT_SFNT_OS2);
169+ TT_Postscript* post = (TT_Postscript*)FT_Get_Sfnt_Table (ft_face, FT_SFNT_POST);
170+
171+ // Weight
172+ if (os2) {
173+ metadata.weight = os2->usWeightClass ;
174+ } else if (head) {
175+ metadata.weight = (head->Mac_Style & (/* condensed */ 1u << 0 )) ? 700 : 400 ;
176+ }
177+
178+ // Width
179+ if (os2) {
180+ metadata.width = getWidth (os2->usWidthClass );
181+ } else if (head) {
182+ if (head->Mac_Style & (/* condensed */ 1u << 5 )) {
183+ metadata.width = 75 .f ;
184+ } else if (head->Mac_Style & (/* expanded */ 1u << 6 )) {
185+ metadata.width = 125 .f ;
186+ }
139187 }
188+
189+ // Italic
190+ if (os2) {
191+ metadata.italic = os2->fsSelection & (/* italic */ 1u << 0 );
192+ } else if (head) {
193+ metadata.italic = head->Mac_Style & (/* italic */ 1u << 1 );
194+ }
195+
196+ // Slant
197+ if (post ) {
198+ metadata.oblique = post ->italicAngle / float (1 << 16 );
199+ }
200+
201+ faces_.emplace_back (std::move (metadata));
140202 } else {
141203 SetError (" font does not have family_name or style_name" );
142204 return ;
@@ -156,6 +218,10 @@ struct AsyncLoad : Napi::AsyncWorker {
156218 if (!face.style_name .empty ()) {
157219 js_face.Set (" style_name" , face.style_name );
158220 }
221+ js_face.Set (" weight" , face.weight );
222+ js_face.Set (" width" , face.width );
223+ js_face.Set (" italic" , face.italic );
224+ js_face.Set (" oblique" , face.oblique );
159225 Napi::Array js_points = Napi::Array::New (env, face.points .size ());
160226 std::uint32_t p_idx = 0 ;
161227 for (auto const & pt : face.points ) {
0 commit comments