44
55#include < algorithm>
66#include < iterator>
7+ #include < set>
78#include < sstream>
89#include < stdexcept>
910#include < string>
@@ -184,11 +185,20 @@ FT2Image::draw_rect_filled(unsigned long x0, unsigned long y0, unsigned long x1,
184185 m_dirty = true ;
185186}
186187
187- static void ft_glyph_warn (FT_ULong charcode)
188+ static void ft_glyph_warn (FT_ULong charcode, std::set<FT_String*> family_names )
188189{
189190 PyObject *text_helpers = NULL , *tmp = NULL ;
191+ std::set<FT_String*>::iterator it = family_names.begin ();
192+ std::stringstream ss;
193+ ss<<*it;
194+ while (++it != family_names.end ()){
195+ ss<<" , " <<*it;
196+ }
197+
190198 if (!(text_helpers = PyImport_ImportModule (" matplotlib._text_helpers" )) ||
191- !(tmp = PyObject_CallMethod (text_helpers, " warn_on_missing_glyph" , " k" , charcode))) {
199+ !(tmp = PyObject_CallMethod (text_helpers,
200+ " warn_on_missing_glyph" , " (k, s)" ,
201+ charcode, ss.str ().c_str ()))) {
192202 goto exit;
193203 }
194204exit:
@@ -199,19 +209,6 @@ static void ft_glyph_warn(FT_ULong charcode)
199209 }
200210}
201211
202- static FT_UInt
203- ft_get_char_index_or_warn (FT_Face face, FT_ULong charcode, bool warn = true )
204- {
205- FT_UInt glyph_index = FT_Get_Char_Index (face, charcode);
206- if (glyph_index) {
207- return glyph_index;
208- }
209- if (warn) {
210- ft_glyph_warn (charcode);
211- }
212- return 0 ;
213- }
214-
215212// ft_outline_decomposer should be passed to FT_Outline_Decompose. On the
216213// first pass, vertices and codes are set to NULL, and index is simply
217214// incremented for each vertex that should be inserted, so that it is set, at
@@ -510,13 +507,13 @@ void FT2Font::set_text(
510507 FT_Pos last_advance;
511508
512509 FT_Error charcode_error, glyph_error;
510+ std::set<FT_String*> glyph_seen_fonts;
513511 FT2Font *ft_object_with_glyph = this ;
514512 bool was_found = load_char_with_fallback (ft_object_with_glyph, glyph_index, glyphs,
515513 char_to_font, glyph_to_font, codepoints[n], flags,
516- charcode_error, glyph_error, false );
514+ charcode_error, glyph_error, glyph_seen_fonts, false );
517515 if (!was_found) {
518- ft_glyph_warn ((FT_ULong)codepoints[n]);
519-
516+ ft_glyph_warn ((FT_ULong)codepoints[n], glyph_seen_fonts);
520517 // render missing glyph tofu
521518 // come back to top-most font
522519 ft_object_with_glyph = this ;
@@ -570,6 +567,7 @@ void FT2Font::load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool
570567 // if this is parent FT2Font, cache will be filled in 2 ways:
571568 // 1. set_text was previously called
572569 // 2. set_text was not called and fallback was enabled
570+ std::set <FT_String *> glyph_seen_fonts;
573571 if (fallback && char_to_font.find (charcode) != char_to_font.end ()) {
574572 ft_object = char_to_font[charcode];
575573 // since it will be assigned to ft_object anyway
@@ -579,10 +577,12 @@ void FT2Font::load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool
579577 FT_UInt final_glyph_index;
580578 FT_Error charcode_error, glyph_error;
581579 FT2Font *ft_object_with_glyph = this ;
582- bool was_found = load_char_with_fallback (ft_object_with_glyph, final_glyph_index, glyphs, char_to_font,
583- glyph_to_font, charcode, flags, charcode_error, glyph_error, true );
580+ bool was_found = load_char_with_fallback (ft_object_with_glyph, final_glyph_index,
581+ glyphs, char_to_font, glyph_to_font,
582+ charcode, flags, charcode_error, glyph_error,
583+ glyph_seen_fonts, true );
584584 if (!was_found) {
585- ft_glyph_warn (charcode);
585+ ft_glyph_warn (charcode, glyph_seen_fonts );
586586 if (charcode_error) {
587587 throw_ft_error (" Could not load charcode" , charcode_error);
588588 }
@@ -592,9 +592,13 @@ void FT2Font::load_char(long charcode, FT_Int32 flags, FT2Font *&ft_object, bool
592592 }
593593 ft_object = ft_object_with_glyph;
594594 } else {
595+ // no fallback case
595596 ft_object = this ;
596- FT_UInt glyph_index = ft_get_char_index_or_warn (face, (FT_ULong)charcode);
597-
597+ FT_UInt glyph_index = FT_Get_Char_Index (face, (FT_ULong) charcode);
598+ if (!glyph_index){
599+ glyph_seen_fonts.insert ((face != NULL )?face->family_name : NULL );
600+ ft_glyph_warn ((FT_ULong)charcode, glyph_seen_fonts);
601+ }
598602 if (FT_Error error = FT_Load_Glyph (face, glyph_index, flags)) {
599603 throw_ft_error (" Could not load charcode" , error);
600604 }
@@ -640,19 +644,21 @@ bool FT2Font::load_char_with_fallback(FT2Font *&ft_object_with_glyph,
640644 FT_Int32 flags,
641645 FT_Error &charcode_error,
642646 FT_Error &glyph_error,
647+ std::set<FT_String*> &glyph_seen_fonts,
643648 bool override = false )
644649{
645650 FT_UInt glyph_index = FT_Get_Char_Index (face, charcode);
651+ glyph_seen_fonts.insert (face->family_name );
646652
647653 if (glyph_index || override ) {
654+
648655 charcode_error = FT_Load_Glyph (face, glyph_index, flags);
649656 if (charcode_error) {
650657 return false ;
651658 }
652-
653659 FT_Glyph thisGlyph;
654660 glyph_error = FT_Get_Glyph (face->glyph , &thisGlyph);
655- if (glyph_error) {
661+ if (glyph_error){
656662 return false ;
657663 }
658664
@@ -667,12 +673,12 @@ bool FT2Font::load_char_with_fallback(FT2Font *&ft_object_with_glyph,
667673 parent_glyphs.push_back (thisGlyph);
668674 return true ;
669675 }
670-
671676 else {
672677 for (size_t i = 0 ; i < fallbacks.size (); ++i) {
673678 bool was_found = fallbacks[i]->load_char_with_fallback (
674679 ft_object_with_glyph, final_glyph_index, parent_glyphs, parent_char_to_font,
675- parent_glyph_to_font, charcode, flags, charcode_error, glyph_error, override );
680+ parent_glyph_to_font, charcode, flags, charcode_error, glyph_error,
681+ glyph_seen_fonts, override );
676682 if (was_found) {
677683 return true ;
678684 }
@@ -721,8 +727,7 @@ FT_UInt FT2Font::get_char_index(FT_ULong charcode, bool fallback = false)
721727 ft_object = this ;
722728 }
723729
724- // historically, get_char_index never raises a warning
725- return ft_get_char_index_or_warn (ft_object->get_face (), charcode, false );
730+ return FT_Get_Char_Index (ft_object->get_face (), charcode);
726731}
727732
728733void FT2Font::get_width_height (long *width, long *height)
0 commit comments