Font_Cache FontFamily_Impl::get_font(const FontDescription &desc, float pixel_ratio) { // Find cached version for (auto &cache : font_cache) { if (cache.pixel_ratio != pixel_ratio) continue; if (desc.get_style() != cache.engine->get_desc().get_style()) continue; if (desc.get_weight() != cache.engine->get_desc().get_weight()) continue; if (desc.get_subpixel() != cache.engine->get_desc().get_subpixel()) continue; if (desc.get_anti_alias() != cache.engine->get_desc().get_anti_alias()) continue; if (cache.engine->is_automatic_recreation_allowed()) { if (desc.get_height() != cache.engine->get_desc().get_height()) continue; } return cache; } return Font_Cache(); }
std::string FontConfig::match_font(const std::string &typeface_name, const FontDescription &desc) const { FcPattern * fc_pattern = nullptr; FcPattern * fc_match = nullptr; try { int weight = static_cast<int>(desc.get_weight()); // Build font matching pattern. fc_pattern = FcPatternBuild(nullptr, FC_FAMILY, FcTypeString, typeface_name.c_str(), FC_PIXEL_SIZE, FcTypeDouble, (double)std::abs(desc.get_height()), FC_WEIGHT, FcTypeInteger, (weight > 0) ? (int)(weight * (FC_WEIGHT_HEAVY / 900.0)) : FC_WEIGHT_NORMAL, FC_SLANT, FcTypeInteger, (desc.get_style() == clan::FontStyle::italic) ? FC_SLANT_ITALIC : ((desc.get_style() == clan::FontStyle::oblique) ? FC_SLANT_OBLIQUE : FC_SLANT_ROMAN), FC_SPACING, FcTypeInteger, FC_PROPORTIONAL, (char*) nullptr ); if (!fc_pattern) { throw Exception("CL_FontConfig: Building FontConfig pattern failed."); } // Execute any needed param substitutions required by the system config. if (FcTrue != FcConfigSubstitute(fc_config, fc_pattern, FcMatchPattern)) { throw Exception("CL_FontConfig: Font config substitutions failed."); } // Supply default values for underspecified font patterns. Never fails. FcDefaultSubstitute(fc_pattern); // Find best match for pattern and extract filename. FcResult match_result; // Doesn't appear to be actually updated. fc_match = FcFontMatch(fc_config, fc_pattern, &match_result); FcChar8 * fc_font_file_path = nullptr; if (FcResultMatch != FcPatternGetString(fc_match, FC_FILE, 0, &fc_font_file_path)) { throw Exception("CL_FontConfig: Could not resolve font pattern to a font file."); } // Release resources and return results. std::string cl_font_file_path((char*)fc_font_file_path); FcPatternDestroy(fc_match); FcPatternDestroy(fc_pattern); return cl_font_file_path; } catch (...) { // If any exceptions thrown, ensure fontconfig resources are released. if (fc_match) FcPatternDestroy(fc_match); if (fc_pattern) FcPatternDestroy(fc_pattern); throw; } }
Font_Cache FontFamily_Impl::copy_font(const FontDescription &desc, float pixel_ratio) { // Find existing typeface, to obtain shared data that we can copy FontFamily_Definition font_definition; bool found = false; // Find find an exact match using style and weight for (auto &definitions : font_definitions) { if (desc.get_style() != definitions.desc.get_style()) continue; if (desc.get_weight() != definitions.desc.get_weight()) continue; font_definition = definitions; found = true; break; } // Else find the first font if (!found) { if (!font_definitions.empty()) { font_definition = font_definitions[0]; found = true; } } if (!found) { // Could not find a cached version of the font to use as reference font_face_load(desc, family_name, pixel_ratio); } else { if (!font_definition.font_databuffer.is_null()) { // Cached font is allocated via a font databuffer font_face_load(desc, font_definition.font_databuffer, pixel_ratio); } else { // Cached font has allocated the typeface_name font_face_load(desc, font_definition.typeface_name, pixel_ratio); } } return font_cache.back(); }