--- src/libnrtype/FontFactory.cpp.stable 2014-10-22 10:50:18.000000000 -0200 +++ src/libnrtype/FontFactory.cpp 2014-10-22 22:32:42.974819481 -0200 @@ -14,6 +14,10 @@ # include "config.h" #endif +#include +#include +#include + #include #include #include // _() @@ -670,6 +674,59 @@ return (style_name_compare(style1.c_str(), style2.c_str()) < 0); } +static char * alloc_user_fonts_list (const char * file, size_t * fonts_list_size) + // + // Read a list of user fonts to be rejected or accepted and + // put it inside a character buffer (it needs to be freed after + // used) +{ + struct stat flist_info; + char * fonts_list = NULL; + + *fonts_list_size = 0; + + if (stat (file, & flist_info) == 0 && + flist_info.st_size > 0 && S_ISREG( flist_info.st_mode ) && (flist_info.st_mode & S_IRUSR) && + (fonts_list = (char *) malloc (flist_info.st_size + 3)) != 0) { + FILE * fin = fopen(file, "r"); + if (fin) { + if (fread(fonts_list + 1, 1, flist_info.st_size, fin) == flist_info.st_size) { + fonts_list[0] = + fonts_list[flist_info.st_size + 1] = '\n'; + fonts_list[flist_info.st_size + 2] = '\0'; + *fonts_list_size = (size_t) flist_info.st_size; + } + else { + free (fonts_list); + fonts_list = NULL; + } + fclose (fin); + } + } + return fonts_list; +} + +static const char * search_user_fonts_list (const char * font_family, const char * fonts_list) + // + // Look for the presence of a particular font inside the user + // font list +{ + const char * pos = NULL; + + if (fonts_list && font_family) { + + int i = strlen (font_family); + pos = fonts_list + 1; // First character is '\n' and is used as a delimter (on both sides) + + for ( ; (pos = strcasestr (pos, font_family)) != NULL ; ) + if (pos[-1] == '\n' && pos[i] == '\n') + break; + else + pos += i; + } + return pos; +} + void font_factory::GetUIFamiliesAndStyles(FamilyToStylesMap *map) { g_assert(map); @@ -679,17 +736,62 @@ // Gather the family names as listed by Pango PangoFontFamily** families = NULL; int numFamilies = 0; + + // Workaround to too many fonts installed on system. + // A kludge is used to deal with just a subset of the installed fonts without disturbing + // other softwares. An analogous method should be used for other important softwares + // too like, for example, libreoffice and browsers to speed-up the loading and cut + // memory usage. Meh, well, lets dream. + + char * home_dir = getenv ("HOME"); + const char * user_config_dir = "/.config/inkscape/", + * fonts_whitelist_file = "fonts.whitelist", + * fonts_blacklist_file = "fonts.blacklist"; + + char * fonts_whitelist = NULL, + * fonts_blacklist = NULL; + size_t fonts_wl_size = 0, + fonts_bl_size = 0; + int fonts_accept = 0, + fonts_reject = 0; + + size_t file_name_size = strlen (home_dir) + strlen (user_config_dir) + strlen (fonts_whitelist_file) + 1; + char * file_name; + + if ((file_name = (char *) malloc (file_name_size)) != NULL) { + strncpy (file_name, home_dir, file_name_size); + strncat (file_name, user_config_dir, file_name_size); + strncat (file_name, fonts_whitelist_file, file_name_size); + fonts_whitelist = alloc_user_fonts_list (file_name, & fonts_wl_size); + + strncpy (file_name, home_dir, file_name_size); + strncat (file_name, user_config_dir, file_name_size); + strncat (file_name, fonts_blacklist_file, file_name_size); + fonts_blacklist = alloc_user_fonts_list (file_name, & fonts_bl_size); + + free (file_name); + } + pango_font_map_list_families(fontServer, &families, &numFamilies); - + for (int currentFamily=0; currentFamily < numFamilies; currentFamily++) { // Gather the styles for this family PangoFontFace** faces = NULL; int numFaces = 0; + const char * font_family = pango_font_family_get_name (families[currentFamily]); + + if (search_user_fonts_list (font_family, fonts_whitelist) != NULL) + fonts_accept ++; + else if (search_user_fonts_list (font_family, fonts_blacklist) != NULL) { + fonts_reject ++; + continue; + } + pango_font_family_list_faces(families[currentFamily], &faces, &numFaces); for (int currentFace=0; currentFace < numFaces; currentFace++) { - + // If the face has a name, describe it, and then use the // description to get the UI family and face strings @@ -754,6 +856,15 @@ (*iter).second.sort(StyleNameCompareInternal); } + if (fonts_blacklist) { + fprintf (stderr, "Blacklisted fonts buffer size: %ld\nFonts rejected: %d\n", fonts_bl_size, fonts_reject); + free (fonts_blacklist); + } + if (fonts_whitelist) { + fprintf (stderr, "Whitelisted fonts buffer size: %ld\nFonts accepted: %d\n", fonts_wl_size, fonts_accept); + free (fonts_whitelist); + } + if (families) g_free(families); }