1 | #include <string> |
2 | #include <algorithm> |
3 | #include <mutex> |
4 | #include <sstream> |
5 | #include <map> |
6 | #include <dirent.h> |
7 | |
8 | #ifdef HAVE_FONT_CONFIG |
9 | #include <fontconfig/fontconfig.h> |
10 | #endif |
11 | |
12 | #include "text_helper.hpp" |
13 | #include "cast_c_array.hpp" |
14 | |
15 | namespace |
16 | { |
17 | #ifdef HAVE_FONT_CONFIG |
18 | class FontConfig |
19 | { |
20 | public: |
21 | static |
22 | FcConfig* |
23 | get(void) |
24 | { |
25 | static FontConfig R; |
26 | return R.m_fc; |
27 | } |
28 | |
29 | static |
30 | std::string |
31 | get_string(FcPattern *pattern, const char *label, std::string default_value = std::string()) |
32 | { |
33 | FcChar8 *value(nullptr); |
34 | if (FcPatternGetString(pattern, label, 0, &value) == FcResultMatch) |
35 | { |
36 | return std::string((const char*)value); |
37 | } |
38 | else |
39 | { |
40 | return default_value; |
41 | } |
42 | } |
43 | |
44 | static |
45 | int |
46 | get_int(FcPattern *pattern, const char *label, int default_value = 0) |
47 | { |
48 | int value(0); |
49 | if (FcPatternGetInteger(pattern, label, 0, &value) == FcResultMatch) |
50 | { |
51 | return value; |
52 | } |
53 | else |
54 | { |
55 | return default_value; |
56 | } |
57 | } |
58 | |
59 | static |
60 | bool |
61 | get_bool(FcPattern *pattern, const char *label, bool default_value = false) |
62 | { |
63 | FcBool value(0); |
64 | if (FcPatternGetBool(pattern, label, 0, &value) == FcResultMatch) |
65 | { |
66 | return value; |
67 | } |
68 | else |
69 | { |
70 | return default_value; |
71 | } |
72 | } |
73 | |
74 | static |
75 | fastuidraw::FontProperties |
76 | get_font_properties(FcPattern *pattern) |
77 | { |
78 | return fastuidraw::FontProperties() |
79 | .style(get_string(pattern, FC_STYLE).c_str()) |
80 | .family(get_string(pattern, FC_FAMILY).c_str()) |
81 | .foundry(get_string(pattern, FC_FOUNDRY).c_str()) |
82 | .source_label(get_string(pattern, FC_FILE).c_str(), |
83 | get_int(pattern, FC_INDEX)) |
84 | .bold(get_int(pattern, FC_WEIGHT) >= FC_WEIGHT_BOLD) |
85 | .italic(get_int(pattern, FC_SLANT) >= FC_SLANT_ITALIC); |
86 | } |
87 | |
88 | private: |
89 | FontConfig(void) |
90 | { |
91 | m_fc = FcInitLoadConfigAndFonts(); |
92 | } |
93 | |
94 | ~FontConfig(void) |
95 | { |
96 | FcConfigDestroy(m_fc); |
97 | } |
98 | |
99 | FcConfig* m_fc; |
100 | }; |
101 | #endif |
102 | /* The purpose of the DaaBufferHolder is to -DELAY- |
103 | * the loading of data until the first time the data |
104 | * is requested. |
105 | */ |
106 | class DataBufferLoader:public fastuidraw::reference_counted<DataBufferLoader>::concurrent |
107 | { |
108 | public: |
109 | explicit |
110 | DataBufferLoader(const std::string &pfilename): |
111 | m_filename(pfilename) |
112 | {} |
113 | |
114 | fastuidraw::reference_counted_ptr<fastuidraw::DataBufferBase> |
115 | buffer(void) |
116 | { |
117 | fastuidraw::reference_counted_ptr<fastuidraw::DataBufferBase> R; |
118 | |
119 | m_mutex.lock(); |
120 | if (!m_buffer) |
121 | { |
122 | m_buffer = FASTUIDRAWnew fastuidraw::DataBuffer(m_filename.c_str()); |
123 | } |
124 | R = m_buffer; |
125 | m_mutex.unlock(); |
126 | |
127 | return R; |
128 | } |
129 | |
130 | private: |
131 | std::string m_filename; |
132 | std::mutex m_mutex; |
133 | fastuidraw::reference_counted_ptr<fastuidraw::DataBufferBase> m_buffer; |
134 | }; |
135 | |
136 | class FreeTypeFontGenerator:public fastuidraw::FontDatabase::FontGeneratorBase |
137 | { |
138 | public: |
139 | FreeTypeFontGenerator(fastuidraw::reference_counted_ptr<DataBufferLoader> buffer, |
140 | fastuidraw::reference_counted_ptr<fastuidraw::FreeTypeLib> lib, |
141 | int face_index, |
142 | const fastuidraw::FontProperties &props): |
143 | m_buffer(buffer), |
144 | m_lib(lib), |
145 | m_face_index(face_index), |
146 | m_props(props) |
147 | {} |
148 | |
149 | virtual |
150 | fastuidraw::reference_counted_ptr<const fastuidraw::FontBase> |
151 | generate_font(void) const |
152 | { |
153 | fastuidraw::reference_counted_ptr<fastuidraw::FreeTypeFace::GeneratorBase> h; |
154 | fastuidraw::reference_counted_ptr<fastuidraw::DataBufferBase> buffer; |
155 | fastuidraw::reference_counted_ptr<const fastuidraw::FontBase> font; |
156 | buffer = m_buffer->buffer(); |
157 | h = FASTUIDRAWnew fastuidraw::FreeTypeFace::GeneratorMemory(buffer, m_face_index); |
158 | font = FASTUIDRAWnew fastuidraw::FontFreeType(h, m_props, m_lib); |
159 | return font; |
160 | } |
161 | |
162 | virtual |
163 | const fastuidraw::FontProperties& |
164 | font_properties(void) const |
165 | { |
166 | return m_props; |
167 | } |
168 | |
169 | private: |
170 | fastuidraw::reference_counted_ptr<DataBufferLoader> m_buffer; |
171 | fastuidraw::reference_counted_ptr<fastuidraw::FreeTypeLib> m_lib; |
172 | int m_face_index; |
173 | fastuidraw::FontProperties m_props; |
174 | }; |
175 | |
176 | void |
177 | preprocess_text(std::string &text) |
178 | { |
179 | /* we want to change '\t' into 4 spaces |
180 | */ |
181 | std::string v; |
182 | v.reserve(text.size() + 4 * std::count(text.begin(), text.end(), '\t')); |
183 | for(std::string::const_iterator iter = text.begin(); iter != text.end(); ++iter) |
184 | { |
185 | if (*iter != '\t') |
186 | { |
187 | v.push_back(*iter); |
188 | } |
189 | else |
190 | { |
191 | v.push_back(' '); |
192 | } |
193 | } |
194 | text.swap(v); |
195 | } |
196 | |
197 | void |
198 | add_fonts_from_file(const std::string &filename, |
199 | fastuidraw::reference_counted_ptr<fastuidraw::FreeTypeLib> lib, |
200 | fastuidraw::reference_counted_ptr<fastuidraw::FontDatabase> font_database) |
201 | { |
202 | FT_Error error_code; |
203 | FT_Face face(nullptr); |
204 | |
205 | lib->lock(); |
206 | error_code = FT_New_Face(lib->lib(), filename.c_str(), 0, &face); |
207 | lib->unlock(); |
208 | |
209 | if (error_code == 0 && face != nullptr && (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) |
210 | { |
211 | fastuidraw::reference_counted_ptr<DataBufferLoader> buffer_loader; |
212 | |
213 | buffer_loader = FASTUIDRAWnew DataBufferLoader(filename); |
214 | for(unsigned int i = 0, endi = face->num_faces; i < endi; ++i) |
215 | { |
216 | fastuidraw::reference_counted_ptr<const fastuidraw::FontDatabase::FontGeneratorBase> h; |
217 | enum fastuidraw::return_code R; |
218 | fastuidraw::FontProperties props; |
219 | if (i != 0) |
220 | { |
221 | lib->lock(); |
222 | FT_Done_Face(face); |
223 | FT_New_Face(lib->lib(), filename.c_str(), i, &face); |
224 | lib->unlock(); |
225 | } |
226 | fastuidraw::FontFreeType::compute_font_properties_from_face(face, props); |
227 | props.source_label(filename.c_str(), i); |
228 | |
229 | h = FASTUIDRAWnew FreeTypeFontGenerator(buffer_loader, lib, i, props); |
230 | R = font_database->add_font_generator(h); |
231 | |
232 | if (R != fastuidraw::routine_success) |
233 | { |
234 | std::cout << "Vanilla warning: unable to add font " << h->font_properties() |
235 | << " because it was already marked as added\n" ; |
236 | } |
237 | else |
238 | { |
239 | // std::cout << "Vanilla add font: " << props << "\n"; |
240 | } |
241 | } |
242 | } |
243 | |
244 | lib->lock(); |
245 | if (face != nullptr) |
246 | { |
247 | FT_Done_Face(face); |
248 | } |
249 | lib->unlock(); |
250 | } |
251 | |
252 | } |
253 | |
254 | ///////////////////////////// |
255 | // GlyphSetGenerator methods |
256 | GlyphSetGenerator:: |
257 | GlyphSetGenerator(fastuidraw::GlyphRenderer r, |
258 | fastuidraw::reference_counted_ptr<const fastuidraw::FontBase> f, |
259 | std::vector<fastuidraw::Glyph> &dst): |
260 | m_render(r), |
261 | m_font(f) |
262 | { |
263 | dst.resize(f->number_glyphs()); |
264 | m_dst = fastuidraw::c_array<fastuidraw::Glyph>(&dst[0], dst.size()); |
265 | SDL_AtomicSet(&m_counter, 0); |
266 | } |
267 | |
268 | int |
269 | GlyphSetGenerator:: |
270 | execute(void *ptr) |
271 | { |
272 | unsigned int idx, K; |
273 | GlyphSetGenerator *p(static_cast<GlyphSetGenerator*>(ptr)); |
274 | |
275 | for(idx = SDL_AtomicAdd(&p->m_counter, 1), K = 0; |
276 | idx < p->m_dst.size(); |
277 | idx = SDL_AtomicAdd(&p->m_counter, 1), ++K) |
278 | { |
279 | p->m_dst[idx] = fastuidraw::Glyph::create_glyph(p->m_render, p->m_font, idx); |
280 | } |
281 | return K; |
282 | } |
283 | |
284 | void |
285 | GlyphSetGenerator:: |
286 | generate(unsigned int num_threads, |
287 | fastuidraw::GlyphRenderer r, |
288 | fastuidraw::reference_counted_ptr<const fastuidraw::FontBase> f, |
289 | std::vector<fastuidraw::Glyph> &dst, |
290 | fastuidraw::GlyphCache &glyph_cache, |
291 | std::vector<int> &cnts) |
292 | { |
293 | GlyphSetGenerator generator(r, f, dst); |
294 | std::vector<SDL_Thread*> threads; |
295 | |
296 | cnts.clear(); |
297 | cnts.resize(fastuidraw::t_max(1u, num_threads), 0); |
298 | |
299 | if (num_threads < 2) |
300 | { |
301 | cnts[0] = execute(&generator); |
302 | } |
303 | else |
304 | { |
305 | for(int i = 0; i < num_threads; ++i) |
306 | { |
307 | threads.push_back(SDL_CreateThread(execute, "" , &generator)); |
308 | } |
309 | |
310 | for(int i = 0; i < num_threads; ++i) |
311 | { |
312 | SDL_WaitThread(threads[i], &cnts[i]); |
313 | } |
314 | } |
315 | |
316 | for(fastuidraw::Glyph glyph : dst) |
317 | { |
318 | if (glyph.valid()) |
319 | { |
320 | enum fastuidraw::return_code R; |
321 | |
322 | R = glyph_cache.add_glyph(glyph, false); |
323 | FASTUIDRAWassert(R == fastuidraw::routine_success); |
324 | FASTUIDRAWunused(R); |
325 | } |
326 | } |
327 | } |
328 | |
329 | ////////////////////////////// |
330 | // global methods |
331 | void |
332 | create_formatted_text(fastuidraw::GlyphSequence &out_sequence, |
333 | const std::vector<uint32_t> &glyph_codes, |
334 | const fastuidraw::FontBase *font, |
335 | const fastuidraw::vec2 &shift_by) |
336 | { |
337 | fastuidraw::vec2 pen(shift_by); |
338 | float format_size(out_sequence.format_size()); |
339 | fastuidraw::GlyphMetrics layout; |
340 | float ratio; |
341 | |
342 | for(uint32_t glyph_code : glyph_codes) |
343 | { |
344 | layout = out_sequence.glyph_cache().fetch_glyph_metrics(font, glyph_code); |
345 | if (layout.valid()) |
346 | { |
347 | out_sequence.add_glyph(fastuidraw::GlyphSource(glyph_code, font), pen); |
348 | |
349 | ratio = format_size / layout.units_per_EM(); |
350 | pen.x() += ratio * layout.advance().x(); |
351 | } |
352 | } |
353 | } |
354 | |
355 | template<typename T> |
356 | static |
357 | void |
358 | create_formatted_textT(T &out_sequence, |
359 | enum fastuidraw::Painter::screen_orientation orientation, |
360 | std::istream &istr, |
361 | const fastuidraw::FontBase *font, |
362 | fastuidraw::reference_counted_ptr<fastuidraw::FontDatabase> font_database, |
363 | const fastuidraw::vec2 &starting_place) |
364 | { |
365 | std::streampos current_position, end_position; |
366 | float format_size(out_sequence.format_size()); |
367 | unsigned int loc(0); |
368 | fastuidraw::vec2 pen(starting_place); |
369 | std::string line, original_line; |
370 | bool first_line(true); |
371 | float pen_y_advance, ratio; |
372 | |
373 | current_position = istr.tellg(); |
374 | istr.seekg(0, std::ios::end); |
375 | end_position = istr.tellg(); |
376 | istr.seekg(current_position, std::ios::beg); |
377 | |
378 | ratio = format_size / font->metrics().units_per_EM(); |
379 | pen_y_advance = ratio * font->metrics().height(); |
380 | |
381 | std::vector<fastuidraw::GlyphSource> glyph_sources; |
382 | std::vector<fastuidraw::vec2> sub_p; |
383 | std::vector<fastuidraw::GlyphMetrics> metrics; |
384 | |
385 | while(getline(istr, line)) |
386 | { |
387 | fastuidraw::c_array<uint32_t> sub_ch; |
388 | fastuidraw::c_array<fastuidraw::range_type<float> > sub_extents; |
389 | bool empty_line; |
390 | |
391 | empty_line = true; |
392 | |
393 | original_line = line; |
394 | preprocess_text(line); |
395 | |
396 | sub_p.resize(line.length()); |
397 | glyph_sources.resize(line.length()); |
398 | metrics.resize(line.length()); |
399 | |
400 | font_database->create_glyph_sequence(font, line.begin(), line.end(), glyph_sources.begin()); |
401 | out_sequence.glyph_cache().fetch_glyph_metrics(cast_c_array(glyph_sources), cast_c_array(metrics)); |
402 | for(unsigned int i = 0, endi = glyph_sources.size(); i < endi; ++i) |
403 | { |
404 | sub_p[i] = pen; |
405 | if (glyph_sources[i].m_font) |
406 | { |
407 | empty_line = false; |
408 | pen.x() += ratio * metrics[i].advance().x(); |
409 | } |
410 | } |
411 | |
412 | if (orientation == fastuidraw::Painter::y_increases_downwards) |
413 | { |
414 | pen.y() += pen_y_advance; |
415 | } |
416 | else |
417 | { |
418 | pen.y() -= pen_y_advance; |
419 | } |
420 | |
421 | pen.x() = starting_place.x(); |
422 | loc += line.length(); |
423 | first_line = false; |
424 | |
425 | out_sequence.add_glyphs(const_cast_c_array(glyph_sources), |
426 | const_cast_c_array(sub_p)); |
427 | } |
428 | } |
429 | |
430 | void |
431 | create_formatted_text(fastuidraw::GlyphSequence &out_sequence, |
432 | enum fastuidraw::Painter::screen_orientation orientation, |
433 | std::istream &istr, |
434 | const fastuidraw::FontBase *font, |
435 | fastuidraw::reference_counted_ptr<fastuidraw::FontDatabase> font_database, |
436 | const fastuidraw::vec2 &starting_place) |
437 | { |
438 | create_formatted_textT(out_sequence, orientation, istr, font, font_database, starting_place); |
439 | } |
440 | |
441 | void |
442 | create_formatted_text(fastuidraw::GlyphRun &out_sequence, |
443 | enum fastuidraw::Painter::screen_orientation orientation, |
444 | std::istream &istr, |
445 | const fastuidraw::FontBase *font, |
446 | fastuidraw::reference_counted_ptr<fastuidraw::FontDatabase> font_database, |
447 | const fastuidraw::vec2 &starting_place) |
448 | { |
449 | create_formatted_textT(out_sequence, orientation, istr, font, font_database, starting_place); |
450 | } |
451 | |
452 | void |
453 | add_fonts_from_path(const std::string &filename, |
454 | fastuidraw::reference_counted_ptr<fastuidraw::FreeTypeLib> lib, |
455 | fastuidraw::reference_counted_ptr<fastuidraw::FontDatabase> font_database) |
456 | { |
457 | DIR *dir; |
458 | struct dirent *entry; |
459 | |
460 | dir = opendir(filename.c_str()); |
461 | if (!dir) |
462 | { |
463 | add_fonts_from_file(filename, lib, font_database); |
464 | return; |
465 | } |
466 | |
467 | for(entry = readdir(dir); entry != nullptr; entry = readdir(dir)) |
468 | { |
469 | std::string file; |
470 | file = entry->d_name; |
471 | if (file != ".." && file != "." ) |
472 | { |
473 | if (filename.empty() || filename.back() != '/') |
474 | { |
475 | add_fonts_from_path(filename + "/" + file, lib, font_database); |
476 | } |
477 | else |
478 | { |
479 | add_fonts_from_path(filename + file, lib, font_database); |
480 | } |
481 | } |
482 | } |
483 | closedir(dir); |
484 | } |
485 | |
486 | fastuidraw::c_string |
487 | default_font(void) |
488 | { |
489 | #ifdef _WIN32 |
490 | { |
491 | return "C:/Windows/Fonts/arial.ttf" ; |
492 | } |
493 | #elif defined(__APPLE__) |
494 | { |
495 | return "/Library/Fonts/Arial.ttf" ; |
496 | } |
497 | #else |
498 | { |
499 | return "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf" ; |
500 | } |
501 | #endif |
502 | } |
503 | |
504 | fastuidraw::c_string |
505 | default_font_path(void) |
506 | { |
507 | #ifdef _WIN32 |
508 | { |
509 | return "C:/Windows/Fonts" ; |
510 | } |
511 | #elif defined(__APPLE__) |
512 | { |
513 | return "/Library/Fonts/" ; |
514 | } |
515 | #else |
516 | { |
517 | return "/usr/share/fonts/" ; |
518 | } |
519 | #endif |
520 | } |
521 | |
522 | void |
523 | add_fonts_from_font_config(fastuidraw::reference_counted_ptr<fastuidraw::FreeTypeLib> lib, |
524 | fastuidraw::reference_counted_ptr<fastuidraw::FontDatabase> font_database) |
525 | { |
526 | #ifdef HAVE_FONT_CONFIG |
527 | { |
528 | FcConfig *config = FontConfig::get(); |
529 | FcObjectSet *object_set; |
530 | FcFontSet *font_set; |
531 | FcPattern* pattern; |
532 | std::map<std::string, fastuidraw::reference_counted_ptr<DataBufferLoader> > buffer_loaders; |
533 | |
534 | object_set = FcObjectSetBuild(FC_FOUNDRY, FC_FAMILY, FC_STYLE, FC_WEIGHT, |
535 | FC_SLANT, FC_SCALABLE, FC_FILE, FC_INDEX, |
536 | FC_LANG, nullptr); |
537 | pattern = FcPatternCreate(); |
538 | FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
539 | font_set = FcFontList(config, pattern, object_set); |
540 | |
541 | for (int i = 0; i < font_set->nfont; ++i) |
542 | { |
543 | std::string filename; |
544 | |
545 | filename = FontConfig::get_string(font_set->fonts[i], FC_FILE); |
546 | if (filename != "" ) |
547 | { |
548 | fastuidraw::reference_counted_ptr<DataBufferLoader> b; |
549 | fastuidraw::reference_counted_ptr<const fastuidraw::FontDatabase::FontGeneratorBase> g; |
550 | std::map<std::string, fastuidraw::reference_counted_ptr<DataBufferLoader> >::const_iterator iter; |
551 | int face_index; |
552 | enum fastuidraw::return_code R; |
553 | fastuidraw::FontProperties props(FontConfig::get_font_properties(font_set->fonts[i])); |
554 | |
555 | iter = buffer_loaders.find(filename); |
556 | if (iter == buffer_loaders.end()) |
557 | { |
558 | b = FASTUIDRAWnew DataBufferLoader(filename); |
559 | buffer_loaders[filename] = b; |
560 | } |
561 | else |
562 | { |
563 | b = iter->second; |
564 | } |
565 | |
566 | face_index = FontConfig::get_int(font_set->fonts[i], FC_INDEX); |
567 | g = FASTUIDRAWnew FreeTypeFontGenerator(b, lib, face_index, props); |
568 | |
569 | R = font_database->add_font_generator(g); |
570 | if (R != fastuidraw::routine_success) |
571 | { |
572 | std::cout << "FontConfig Warning: unable to add font " << props |
573 | << " because it was already marked as added\n" ; |
574 | } |
575 | else |
576 | { |
577 | // std::cout << "FontConfig add font: " << props << "\n"; |
578 | } |
579 | } |
580 | } |
581 | FcFontSetDestroy(font_set); |
582 | FcPatternDestroy(pattern); |
583 | FcObjectSetDestroy(object_set); |
584 | } |
585 | #endif |
586 | } |
587 | |
588 | fastuidraw::reference_counted_ptr<const fastuidraw::FontBase> |
589 | select_font_font_config(int weight, int slant, |
590 | fastuidraw::c_string style, |
591 | fastuidraw::c_string family, |
592 | fastuidraw::c_string foundry, |
593 | const std::set<std::string> &langs, |
594 | fastuidraw::reference_counted_ptr<fastuidraw::FreeTypeLib> lib, |
595 | fastuidraw::reference_counted_ptr<fastuidraw::FontDatabase> font_database) |
596 | { |
597 | #ifdef HAVE_FONT_CONFIG |
598 | { |
599 | FcConfig *config = FontConfig::get(); |
600 | FcPattern* pattern; |
601 | FcLangSet* lang_set(nullptr); |
602 | |
603 | pattern = FcPatternCreate(); |
604 | if (weight >= 0) |
605 | { |
606 | FcPatternAddInteger(pattern, FC_WEIGHT, weight); |
607 | } |
608 | |
609 | if (slant >= 0) |
610 | { |
611 | FcPatternAddInteger(pattern, FC_SLANT, slant); |
612 | } |
613 | |
614 | if (style) |
615 | { |
616 | FcPatternAddString(pattern, FC_STYLE, (const FcChar8*)style); |
617 | } |
618 | |
619 | if (family) |
620 | { |
621 | FcPatternAddString(pattern, FC_FAMILY, (const FcChar8*)family); |
622 | } |
623 | |
624 | if (foundry) |
625 | { |
626 | FcPatternAddString(pattern, FC_FOUNDRY, (const FcChar8*)foundry); |
627 | } |
628 | |
629 | for (const std::string &lang : langs) |
630 | { |
631 | if (!lang_set) |
632 | { |
633 | lang_set = FcLangSetCreate(); |
634 | } |
635 | FcLangSetAdd(lang_set, (const FcChar8*)lang.c_str()); |
636 | } |
637 | |
638 | if (lang_set) |
639 | { |
640 | FcPatternAddLangSet(pattern, FC_LANG, lang_set); |
641 | } |
642 | |
643 | FcPatternAddBool(pattern, FC_SCALABLE, FcTrue); |
644 | |
645 | FcConfigSubstitute(config, pattern, FcMatchPattern); |
646 | FcDefaultSubstitute(pattern); |
647 | |
648 | FcResult r; |
649 | FcPattern *font_pattern = FcFontMatch(config, pattern, &r); |
650 | fastuidraw::reference_counted_ptr<const fastuidraw::FontBase> font; |
651 | |
652 | if (font_pattern) |
653 | { |
654 | FcChar8* filename(nullptr); |
655 | if (FcPatternGetString(font_pattern, FC_FILE, 0, &filename) == FcResultMatch) |
656 | { |
657 | int face_index; |
658 | |
659 | face_index = FontConfig::get_int(font_pattern, FC_INDEX); |
660 | font = font_database->fetch_font((fastuidraw::c_string)filename, face_index); |
661 | if (!font) |
662 | { |
663 | fastuidraw::FontProperties props; |
664 | fastuidraw::reference_counted_ptr<FreeTypeFontGenerator> gen; |
665 | fastuidraw::reference_counted_ptr<DataBufferLoader> buffer_loader; |
666 | |
667 | props = FontConfig::get_font_properties(font_pattern); |
668 | buffer_loader = FASTUIDRAWnew DataBufferLoader(std::string((const char*)filename)); |
669 | gen = FASTUIDRAWnew FreeTypeFontGenerator(buffer_loader, lib, face_index, props); |
670 | |
671 | font = font_database->fetch_or_generate_font(gen); |
672 | } |
673 | } |
674 | FcPatternDestroy(font_pattern); |
675 | } |
676 | FcPatternDestroy(pattern); |
677 | if (lang_set) |
678 | { |
679 | FcLangSetDestroy(lang_set); |
680 | } |
681 | return font; |
682 | } |
683 | #else |
684 | { |
685 | fastuidraw::FontProperties props; |
686 | uint32_t flags(0u); |
687 | |
688 | if (foundry) |
689 | { |
690 | props.foundry(foundry); |
691 | } |
692 | |
693 | if (family) |
694 | { |
695 | props.family(family); |
696 | } |
697 | |
698 | if (style) |
699 | { |
700 | props.style(style); |
701 | } |
702 | else |
703 | { |
704 | flags |= fastuidraw::FontDatabase::ignore_style; |
705 | } |
706 | |
707 | if (weight >=0 && slant >= 0) |
708 | { |
709 | props |
710 | .bold(weight >= 200) |
711 | .italic(slant >= 100); |
712 | } |
713 | else |
714 | { |
715 | flags |= fastuidraw::FontDatabase::ignore_bold_italic; |
716 | } |
717 | |
718 | return font_database->fetch_font(props, flags); |
719 | } |
720 | #endif |
721 | } |
722 | |