1 #include "..\..\..\StdAfx.h"
3 #include "texture_atlas.h"
4 #include "texture_font.h"
11 namespace caspar { namespace core { namespace text {
13 struct freetype_exception : virtual caspar_exception
15 freetype_exception() {}
16 explicit freetype_exception(const char* msg) : caspar_exception(msg) {}
25 unicode_range get_range(unicode_block block);
28 struct texture_font::impl
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)
36 float left, top, right, bottom;
44 std::map<int, glyph_info> glyphs_;
47 impl::impl(texture_atlas& atlas, const std::wstring& filename, float size) : lib_(nullptr), face_(nullptr), atlas_(atlas), size_(size)
52 err = FT_Init_FreeType(&lib_);
53 if(err) throw freetype_exception("Failed to initialize freetype");
55 err = FT_New_Face(lib_, u8(filename).c_str(), 0, &face_);
56 if(err) throw freetype_exception("Failed to load font");
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");
61 catch(std::exception& ex)
66 FT_Done_FreeType(lib_);
77 FT_Done_FreeType(lib_);
80 int count_glyphs_in_range(unicode_block block)
82 unicode_range range = get_range(block);
84 //TODO: extract info from freetype
86 //very pesimistic, assumes a glyph for each charcode
87 return range.last - range.first;
90 void impl::load_glyphs(unicode_block block, const color<float>& col)
93 int flags = FT_LOAD_RENDER | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL;
94 unicode_range range = get_range(block);
96 for(int i = range.first; i <= range.last; ++i)
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.
102 err = FT_Load_Glyph(face_, glyph_index, flags);
103 if(err) continue; //igonore glyphs that fail to load
105 const FT_Bitmap& bitmap = face_->glyph->bitmap; //shorthand notation
107 auto region = atlas_.get_region(bitmap.width+1, bitmap.rows+1);
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
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())));
124 std::vector<float> create_vertex_stream(const std::wstring& str, int x, int y, int parent_width, int parent_height)
126 //TODO: detect glyphs that aren't in the atlas and load them (and maybe that entire unicode_block on the fly
128 std::vector<float> result(16*str.length(), 0);
130 bool use_kerning = (face_->face_flags & FT_FACE_FLAG_KERNING) == FT_FACE_FLAG_KERNING;
132 FT_UInt previous = 0;
133 float pos_x = (float)x;
134 float pos_y = (float)y;
136 auto end = str.end();
137 for(auto it = str.begin(); it != end; ++it, ++index)
139 auto glyph_it = glyphs_.find(*it);
140 if(glyph_it != glyphs_.end())
142 const glyph_info& coords = glyph_it->second;
144 FT_UInt glyph_index = FT_Get_Char_Index(face_, (*it));
146 if(use_kerning && previous && glyph_index)
149 FT_Get_Kerning(face_, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
151 pos_x += delta.x / 64.0f;
154 FT_Load_Glyph(face_, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL);
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;
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;
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
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
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
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
186 pos_x += face_->glyph->advance.x / 64.0f;
187 previous = glyph_index;
193 string_metrics measure_string(const std::wstring& str)
195 string_metrics result;
197 bool use_kerning = (face_->face_flags & FT_FACE_FLAG_KERNING) == FT_FACE_FLAG_KERNING;
199 FT_UInt previous = 0;
203 auto end = str.end();
204 for(auto it = str.begin(); it != end; ++it, ++index)
206 auto glyph_it = glyphs_.find(*it);
207 if(glyph_it != glyphs_.end())
209 const glyph_info& coords = glyph_it->second;
211 FT_UInt glyph_index = FT_Get_Char_Index(face_, (*it));
213 if(use_kerning && previous && glyph_index)
216 FT_Get_Kerning(face_, previous, glyph_index, FT_KERNING_DEFAULT, &delta);
218 pos_x += delta.x / 64.0f;
221 FT_Load_Glyph(face_, glyph_index, FT_LOAD_NO_BITMAP | FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_NORMAL);
223 int bearingY = face_->glyph->metrics.horiBearingY >> 6;
224 if(bearingY > result.bearingY)
225 result.bearingY = bearingY;
227 if(coords.height > result.height)
228 result.height = coords.height;
230 pos_x += face_->glyph->advance.x / 64.0f;
231 previous = glyph_index;
235 result.width = (int)(pos_x+.5f);
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); }
245 unicode_range get_range(unicode_block block)
248 unicode_range range = {0x0000, 0x007F};
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);