]> git.sesse.net Git - casparcg/blob - core/producer/text/utils/texture_font.cpp
* added geometry to frames for custom rendering
[casparcg] / core / producer / text / utils / texture_font.cpp
1 #include "..\..\..\StdAfx.h"
2
3 #include "texture_atlas.h"
4 #include "texture_font.h"
5
6 #include <map>
7 #include <ft2build.h>
8 #include FT_FREETYPE_H
9 #include FT_GLYPH_H
10
11 namespace caspar { namespace core { namespace text {
12
13 struct freetype_exception : virtual caspar_exception
14 {
15         freetype_exception() {}
16         explicit freetype_exception(const char* msg) : caspar_exception(msg) {}
17 };
18
19 struct unicode_range
20 {
21         int first;
22         int last;
23 };
24
25 unicode_range get_range(unicode_block block);
26
27
28 struct texture_font::impl
29 {
30 private:
31         struct glyph_info
32         {
33                 glyph_info(int w, int h, float l, float t, float r, float b) : width(w), height(h), left(l), top(t), right(r), bottom(b)
34                 {}
35
36                 float left, top, right, bottom;
37                 int width, height;
38         };
39
40         FT_Library              lib_;
41         FT_Face                 face_;
42         texture_atlas   atlas_;
43         float                   size_;
44         std::map<int, glyph_info> glyphs_;
45
46 public:
47         impl::impl(texture_atlas& atlas, const std::wstring& filename, float size) : lib_(nullptr), face_(nullptr), atlas_(atlas), size_(size)
48         {
49                 try
50                 {
51                         FT_Error err;
52                         err = FT_Init_FreeType(&lib_);
53                         if(err) throw freetype_exception("Failed to initialize freetype");
54
55                         err = FT_New_Face(lib_, u8(filename).c_str(), 0, &face_);
56                         if(err) throw freetype_exception("Failed to load font");
57
58                         err = FT_Set_Char_Size(face_, (FT_F26Dot6)(size*64), 0, 72, 72);
59                         if(err) throw freetype_exception("Failed to set font size");
60                 }
61                 catch(std::exception& ex)
62                 {
63                         if(face_ != nullptr)
64                                 FT_Done_Face(face_);
65                         if(lib_ != nullptr)
66                                 FT_Done_FreeType(lib_);
67
68                         throw ex;
69                 }
70         }
71
72         ~impl()
73         {
74                 if(face_ != nullptr)
75                         FT_Done_Face(face_);
76                 if(lib_ != nullptr)
77                         FT_Done_FreeType(lib_);
78         }
79
80         int count_glyphs_in_range(unicode_block block)
81         { 
82                 unicode_range range = get_range(block);
83
84                 //TODO: extract info from freetype
85
86                 //very pesimistic, assumes a glyph for each charcode
87                 return range.last - range.first;
88         }
89
90         void impl::load_glyphs(unicode_block block, const color<float>& col)
91         {
92                 FT_Error err;
93                 int flags = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL;
94                 unicode_range range = get_range(block);
95
96                 for(int i = range.first; i <= range.last; ++i)
97                 {
98                         FT_UInt glyph_index = FT_Get_Char_Index(face_, i);
99                         if(!glyph_index)        //ignore codes that doesn't have a glyph for now. Might want to map these to a special glyph later.
100                                 continue;
101                         
102                         err = FT_Load_Glyph(face_, glyph_index, flags);
103                         if(err) continue;       //igonore glyphs that fail to load
104
105                         const FT_Bitmap& bitmap = face_->glyph->bitmap; //shorthand notation
106
107                         auto region = atlas_.get_region(bitmap.width+1, bitmap.rows+1);
108                         if(region.x < 0)
109                         {
110                                 //the glyph doesn't fit in the texture-atlas. ignore it for now.
111                                 //we might want to restart with a bigger atlas in the future
112                                 continue;
113                         }
114
115                         atlas_.set_region(region.x, region.y, bitmap.width, bitmap.rows, bitmap.buffer, bitmap.pitch, col);
116                         glyphs_.insert(std::pair<int, glyph_info>(i, glyph_info(bitmap.width, bitmap.rows, 
117                                                                                 region.x / (float)atlas_.width(), 
118                                                                                 region.y / (float)atlas_.height(), 
119                                                                                 (region.x + bitmap.width) / (float)atlas_.width(), 
120                                                                                 (region.y + bitmap.rows) / (float)atlas_.height())));
121                 }
122         }
123
124         std::vector<float> create_vertex_stream(const std::wstring& str, int x, int y, int parent_width, int parent_height)
125         {
126                 //TODO: detect glyphs that aren't in the atlas and load them (and maybe that entire unicode_block on the fly
127
128                 std::vector<float> result(16*str.length(), 0);
129
130                 bool use_kerning = (face_->face_flags & FT_FACE_FLAG_KERNING) == FT_FACE_FLAG_KERNING;
131                 int index = 0;
132                 FT_UInt previous = 0;
133                 float pos_x = (float)x;
134                 float pos_y = (float)y;
135
136                 auto end = str.end();
137                 for(auto it = str.begin(); it != end; ++it, ++index)
138                 {
139                         auto glyph_it = glyphs_.find(*it);
140                         if(glyph_it != glyphs_.end())
141                         {       
142                                 const glyph_info& coords = glyph_it->second;
143
144                                 FT_UInt glyph_index = FT_Get_Char_Index(face_, (*it));
145
146                                 if(use_kerning && previous && glyph_index)
147                                 {
148                                         FT_Vector delta;
149                                         FT_Get_Kerning(face_, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
150
151                                         pos_x += delta.x / 64.0f;
152                                 }
153
154                                 FT_Load_Glyph(face_, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL);
155
156                                 float left = (pos_x + face_->glyph->metrics.horiBearingX/64.0f) / parent_width ;
157                                 float right = ((pos_x + face_->glyph->metrics.horiBearingX/64.0f) + coords.width) / parent_width;
158
159                                 float top = (pos_y - face_->glyph->metrics.horiBearingY/64.0f) / parent_height;
160                                 float bottom = ((pos_y - face_->glyph->metrics.horiBearingY/64.0f) + coords.height) / parent_height;
161
162                                 //vertex 1 top left
163                                 result[index*16 + 0] = left;                    //vertex.x
164                                 result[index*16 + 1] = top;                             //vertex.y
165                                 result[index*16 + 2] = coords.left;             //texcoord.r
166                                 result[index*16 + 3] = coords.top;              //texcoord.s
167
168                                 //vertex 2 top right
169                                 result[index*16 + 4] = right;                   //vertex.x
170                                 result[index*16 + 5] = top;                             //vertex.y
171                                 result[index*16 + 6] = coords.right;    //texcoord.r
172                                 result[index*16 + 7] = coords.top;              //texcoord.s
173
174                                 //vertex 3 bottom right
175                                 result[index*16 + 8] = right;                   //vertex.x
176                                 result[index*16 + 9] = bottom;                  //vertex.y
177                                 result[index*16 + 10] = coords.right;   //texcoord.r
178                                 result[index*16 + 11] = coords.bottom;  //texcoord.s
179
180                                 //vertex 4 bottom left
181                                 result[index*16 + 12] = left;                   //vertex.x
182                                 result[index*16 + 13] = bottom;                 //vertex.y
183                                 result[index*16 + 14] = coords.left;    //texcoord.r
184                                 result[index*16 + 15] = coords.bottom;  //texcoord.s
185
186                                 pos_x += face_->glyph->advance.x / 64.0f;
187                                 previous = glyph_index;
188                         }
189                 }
190                 return result;
191         }
192
193         string_metrics measure_string(const std::wstring& str)
194         {
195                 string_metrics result;
196                 
197                 bool use_kerning = (face_->face_flags & FT_FACE_FLAG_KERNING) == FT_FACE_FLAG_KERNING;
198                 int index = 0;
199                 FT_UInt previous = 0;
200                 float pos_x = 0;
201 //              float pos_y = 0;
202
203                 auto end = str.end();
204                 for(auto it = str.begin(); it != end; ++it, ++index)
205                 {
206                         auto glyph_it = glyphs_.find(*it);
207                         if(glyph_it != glyphs_.end())
208                         {       
209                                 const glyph_info& coords = glyph_it->second;
210
211                                 FT_UInt glyph_index = FT_Get_Char_Index(face_, (*it));
212
213                                 if(use_kerning && previous && glyph_index)
214                                 {
215                                         FT_Vector delta;
216                                         FT_Get_Kerning(face_, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
217
218                                         pos_x += delta.x / 64.0f;
219                                 }
220
221                                 FT_Load_Glyph(face_, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL);
222
223                                 int bearingY = face_->glyph->metrics.horiBearingY >> 6;
224                                 if(bearingY > result.bearingY)
225                                         result.bearingY = bearingY;
226
227                                 if(coords.height > result.height)
228                                         result.height = coords.height;
229
230                                 pos_x += face_->glyph->advance.x / 64.0f;
231                                 previous = glyph_index;
232                         }
233                 }
234
235                 result.width = (int)(pos_x+.5f);
236                 return result;
237         }
238 }; 
239
240 texture_font::texture_font(texture_atlas& atlas, const std::wstring& filename, float size) : impl_(new impl(atlas, filename, size)) {}
241 void texture_font::load_glyphs(unicode_block range, const color<float>& col) { impl_->load_glyphs(range, col); }
242 std::vector<float> texture_font::create_vertex_stream(const std::wstring& str, int x, int y, int parent_width, int parent_height) { return impl_->create_vertex_stream(str, x, y, parent_width, parent_height); }
243 string_metrics texture_font::measure_string(const std::wstring& str) { return impl_->measure_string(str); }
244
245 unicode_range get_range(unicode_block block)
246 {
247         //TODO: implement
248         unicode_range range = {0x0000, 0x007F};
249         return range;
250 }
251
252 }}}
253
254 //unicode blocks
255 /*
256                 range(0x0000, 0x007F); 
257                 range(0x0080, 0x00FF); 
258                 range(0x0100, 0x017F); 
259                 range(0x0180, 0x024F); 
260                 range(0x0250, 0x02AF); 
261                 range(0x02B0, 0x02FF); 
262                 range(0x0300, 0x036F); 
263                 range(0x0370, 0x03FF); 
264                 range(0x0400, 0x04FF); 
265                 range(0x0500, 0x052F); 
266                 range(0x0530, 0x058F); 
267                 range(0x0590, 0x05FF); 
268                 range(0x0600, 0x06FF); 
269                 range(0x0700, 0x074F); 
270                 range(0x0750, 0x077F); 
271                 range(0x0780, 0x07BF); 
272                 range(0x07C0, 0x07FF); 
273                 range(0x0800, 0x083F); 
274                 range(0x0840, 0x085F); 
275                 range(0x08A0, 0x08FF); 
276                 range(0x0900, 0x097F); 
277                 range(0x0980, 0x09FF); 
278                 range(0x0A00, 0x0A7F); 
279                 range(0x0A80, 0x0AFF); 
280                 range(0x0B00, 0x0B7F); 
281                 range(0x0B80, 0x0BFF); 
282                 range(0x0C00, 0x0C7F); 
283                 range(0x0C80, 0x0CFF); 
284                 range(0x0D00, 0x0D7F); 
285                 range(0x0D80, 0x0DFF); 
286                 range(0x0E00, 0x0E7F); 
287                 range(0x0E80, 0x0EFF); 
288                 range(0x0F00, 0x0FFF); 
289                 range(0x1000, 0x109F); 
290                 range(0x10A0, 0x10FF); 
291                 range(0x1100, 0x11FF); 
292                 range(0x1200, 0x137F); 
293                 range(0x1380, 0x139F); 
294                 range(0x13A0, 0x13FF); 
295                 range(0x1400, 0x167F); 
296                 range(0x1680, 0x169F); 
297                 range(0x16A0, 0x16FF); 
298                 range(0x1700, 0x171F); 
299                 range(0x1720, 0x173F); 
300                 range(0x1740, 0x175F); 
301                 range(0x1760, 0x177F); 
302                 range(0x1780, 0x17FF); 
303                 range(0x1800, 0x18AF); 
304                 range(0x18B0, 0x18FF); 
305                 range(0x1900, 0x194F); 
306                 range(0x1950, 0x197F); 
307                 range(0x1980, 0x19DF); 
308                 range(0x19E0, 0x19FF); 
309                 range(0x1A00, 0x1A1F); 
310                 range(0x1A20, 0x1AAF); 
311                 range(0x1B00, 0x1B7F); 
312                 range(0x1B80, 0x1BBF); 
313                 range(0x1BC0, 0x1BFF); 
314                 range(0x1C00, 0x1C4F); 
315                 range(0x1C50, 0x1C7F); 
316                 range(0x1CC0, 0x1CCF); 
317                 range(0x1CD0, 0x1CFF); 
318                 range(0x1D00, 0x1D7F); 
319                 range(0x1D80, 0x1DBF); 
320                 range(0x1DC0, 0x1DFF); 
321                 range(0x1E00, 0x1EFF); 
322                 range(0x1F00, 0x1FFF); 
323                 range(0x2000, 0x206F); 
324                 range(0x2070, 0x209F); 
325                 range(0x20A0, 0x20CF); 
326                 range(0x20D0, 0x20FF); 
327                 range(0x2100, 0x214F); 
328                 range(0x2150, 0x218F); 
329                 range(0x2190, 0x21FF); 
330                 range(0x2200, 0x22FF); 
331                 range(0x2300, 0x23FF); 
332                 range(0x2400, 0x243F); 
333                 range(0x2440, 0x245F); 
334                 range(0x2460, 0x24FF); 
335                 range(0x2500, 0x257F); 
336                 range(0x2580, 0x259F); 
337                 range(0x25A0, 0x25FF); 
338                 range(0x2600, 0x26FF); 
339                 range(0x2700, 0x27BF); 
340                 range(0x27C0, 0x27EF); 
341                 range(0x27F0, 0x27FF); 
342                 range(0x2800, 0x28FF); 
343                 range(0x2900, 0x297F); 
344                 range(0x2980, 0x29FF); 
345                 range(0x2A00, 0x2AFF); 
346                 range(0x2B00, 0x2BFF); 
347                 range(0x2C00, 0x2C5F); 
348                 range(0x2C60, 0x2C7F); 
349                 range(0x2C80, 0x2CFF); 
350                 range(0x2D00, 0x2D2F); 
351                 range(0x2D30, 0x2D7F); 
352                 range(0x2D80, 0x2DDF); 
353                 range(0x2DE0, 0x2DFF); 
354                 range(0x2E00, 0x2E7F); 
355                 range(0x2E80, 0x2EFF); 
356                 range(0x2F00, 0x2FDF); 
357                 range(0x2FF0, 0x2FFF); 
358                 range(0x3000, 0x303F); 
359                 range(0x3040, 0x309F); 
360                 range(0x30A0, 0x30FF); 
361                 range(0x3100, 0x312F); 
362                 range(0x3130, 0x318F); 
363                 range(0x3190, 0x319F); 
364                 range(0x31A0, 0x31BF); 
365                 range(0x31C0, 0x31EF); 
366                 range(0x31F0, 0x31FF); 
367                 range(0x3200, 0x32FF); 
368                 range(0x3300, 0x33FF); 
369                 range(0x3400, 0x4DBF); 
370                 range(0x4DC0, 0x4DFF); 
371                 range(0x4E00, 0x9FFF); 
372                 range(0xA000, 0xA48F); 
373                 range(0xA490, 0xA4CF); 
374                 range(0xA4D0, 0xA4FF); 
375                 range(0xA500, 0xA63F); 
376                 range(0xA640, 0xA69F); 
377                 range(0xA6A0, 0xA6FF); 
378                 range(0xA700, 0xA71F); 
379                 range(0xA720, 0xA7FF); 
380                 range(0xA800, 0xA82F); 
381                 range(0xA830, 0xA83F); 
382                 range(0xA840, 0xA87F); 
383                 range(0xA880, 0xA8DF); 
384                 range(0xA8E0, 0xA8FF); 
385                 range(0xA900, 0xA92F); 
386                 range(0xA930, 0xA95F); 
387                 range(0xA960, 0xA97F); 
388                 range(0xA980, 0xA9DF); 
389                 range(0xAA00, 0xAA5F); 
390                 range(0xAA60, 0xAA7F); 
391                 range(0xAA80, 0xAADF); 
392                 range(0xAAE0, 0xAAFF); 
393                 range(0xAB00, 0xAB2F); 
394                 range(0xABC0, 0xABFF); 
395                 range(0xAC00, 0xD7AF); 
396                 range(0xD7B0, 0xD7FF); 
397                 range(0xD800, 0xDB7F); 
398                 range(0xDB80, 0xDBFF); 
399                 range(0xDC00, 0xDFFF); 
400                 range(0xE000, 0xF8FF); 
401                 range(0xF900, 0xFAFF); 
402                 range(0xFB00, 0xFB4F); 
403                 range(0xFB50, 0xFDFF); 
404                 range(0xFE00, 0xFE0F); 
405                 range(0xFE10, 0xFE1F); 
406                 range(0xFE20, 0xFE2F); 
407                 range(0xFE30, 0xFE4F); 
408                 range(0xFE50, 0xFE6F); 
409                 range(0xFE70, 0xFEFF); 
410                 range(0xFF00, 0xFFEF); 
411                 range(0xFFF0, 0xFFFF); 
412                 range(0x10000, 0x1007F); 
413                 range(0x10080, 0x100FF); 
414                 range(0x10100, 0x1013F); 
415                 range(0x10140, 0x1018F); 
416                 range(0x10190, 0x101CF); 
417                 range(0x101D0, 0x101FF); 
418                 range(0x10280, 0x1029F); 
419                 range(0x102A0, 0x102DF); 
420                 range(0x10300, 0x1032F); 
421                 range(0x10330, 0x1034F); 
422                 range(0x10380, 0x1039F); 
423                 range(0x103A0, 0x103DF); 
424                 range(0x10400, 0x1044F); 
425                 range(0x10450, 0x1047F); 
426                 range(0x10480, 0x104AF); 
427                 range(0x10800, 0x1083F); 
428                 range(0x10840, 0x1085F); 
429                 range(0x10900, 0x1091F); 
430                 range(0x10920, 0x1093F); 
431                 range(0x10980, 0x1099F); 
432                 range(0x109A0, 0x109FF); 
433                 range(0x10A00, 0x10A5F); 
434                 range(0x10A60, 0x10A7F); 
435                 range(0x10B00, 0x10B3F); 
436                 range(0x10B40, 0x10B5F); 
437                 range(0x10B60, 0x10B7F); 
438                 range(0x10C00, 0x10C4F); 
439                 range(0x10E60, 0x10E7F); 
440                 range(0x11000, 0x1107F); 
441                 range(0x11080, 0x110CF); 
442                 range(0x110D0, 0x110FF); 
443                 range(0x11100, 0x1114F); 
444                 range(0x11180, 0x111DF); 
445                 range(0x11680, 0x116CF); 
446                 range(0x12000, 0x123FF); 
447                 range(0x12400, 0x1247F); 
448                 range(0x13000, 0x1342F); 
449                 range(0x16800, 0x16A3F); 
450                 range(0x16F00, 0x16F9F); 
451                 range(0x1B000, 0x1B0FF); 
452                 range(0x1D000, 0x1D0FF); 
453                 range(0x1D100, 0x1D1FF); 
454                 range(0x1D200, 0x1D24F); 
455                 range(0x1D300, 0x1D35F); 
456                 range(0x1D360, 0x1D37F); 
457                 range(0x1D400, 0x1D7FF); 
458                 range(0x1EE00, 0x1EEFF); 
459                 range(0x1F000, 0x1F02F); 
460                 range(0x1F030, 0x1F09F); 
461                 range(0x1F0A0, 0x1F0FF); 
462                 range(0x1F100, 0x1F1FF); 
463                 range(0x1F200, 0x1F2FF); 
464                 range(0x1F300, 0x1F5FF); 
465                 range(0x1F600, 0x1F64F); 
466                 range(0x1F680, 0x1F6FF); 
467                 range(0x1F700, 0x1F77F); 
468                 range(0x20000, 0x2A6DF); 
469                 range(0x2A700, 0x2B73F); 
470                 range(0x2B740, 0x2B81F); 
471                 range(0x2F800, 0x2FA1F); 
472                 range(0xE0000, 0xE007F); 
473                 range(0xE0100, 0xE01EF); 
474                 range(0xF0000, 0xFFFFF); 
475                 range(0x100000, 0x10FFFF);
476 */