From db7924d646915a3464e416169dab92e077b387fa Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 1 Feb 2012 04:17:33 +0000 Subject: [PATCH] Add a warning in the fontconfig font collector when the chosen font does not have glyphs for some of the characters used in that font Originally committed to SVN as r6417. --- aegisub/src/font_file_lister.cpp | 23 +++++++++------------ aegisub/src/font_file_lister.h | 9 ++++---- aegisub/src/font_file_lister_fontconfig.cpp | 18 +++++++++++++++- aegisub/src/font_file_lister_fontconfig.h | 3 ++- aegisub/src/font_file_lister_freetype.cpp | 2 +- aegisub/src/font_file_lister_freetype.h | 2 +- 6 files changed, 36 insertions(+), 21 deletions(-) diff --git a/aegisub/src/font_file_lister.cpp b/aegisub/src/font_file_lister.cpp index 971264093..04f97cfff 100644 --- a/aegisub/src/font_file_lister.cpp +++ b/aegisub/src/font_file_lister.cpp @@ -47,17 +47,11 @@ void FontCollector::ProcessDialogueLine(AssDialogue *line) { if (line->Comment) return; line->ParseASSTags(); - bool text = false; StyleInfo style = styles[line->Style]; StyleInfo initial = style; for (size_t i = 0; i < line->Blocks.size(); ++i) { if (AssDialogueBlockOverride *ovr = dynamic_cast(line->Blocks[i])) { - if (text) { - used_styles.insert(style); - text = false; - } - for (size_t j = 0; j < ovr->Tags.size(); ++j) { AssOverrideTag *tag = ovr->Tags[j]; wxString name = tag->Name; @@ -75,26 +69,29 @@ void FontCollector::ProcessDialogueLine(AssDialogue *line) { } } else if (AssDialogueBlockPlain *txt = dynamic_cast(line->Blocks[i])) { - text = text || !txt->GetText().empty(); + wxString text = txt->GetText(); + if (text.size()) { + std::set& chars = used_styles[style]; + for (size_t i = 0; i < text.size(); ++i) + chars.insert(text[i]); + } } // Do nothing with drawing blocks } - if (text) - used_styles.insert(style); line->ClearBlocks(); } -void FontCollector::ProcessChunk(StyleInfo const& style) { - std::vector paths = lister.GetFontPaths(style.facename, style.bold, style.italic); +void FontCollector::ProcessChunk(std::pair > const& style) { + std::vector paths = lister.GetFontPaths(style.first.facename, style.first.bold, style.first.italic, style.second); if (paths.empty()) { - status_callback(wxString::Format("Could not find font '%s'\n", style.facename), 2); + status_callback(wxString::Format("Could not find font '%s'\n", style.first.facename), 2); ++missing; } else { for (size_t i = 0; i < paths.size(); ++i) { if (results.insert(paths[i]).second) - status_callback(wxString::Format("Found '%s' at '%s'\n", style.facename, paths[i]), 0); + status_callback(wxString::Format("Found '%s' at '%s'\n", style.first.facename, paths[i]), 0); } } } diff --git a/aegisub/src/font_file_lister.h b/aegisub/src/font_file_lister.h index c4d241e99..9dfe2eec6 100644 --- a/aegisub/src/font_file_lister.h +++ b/aegisub/src/font_file_lister.h @@ -46,8 +46,9 @@ public: /// @param facename Name of font face /// @param bold ASS font weight /// @param italic Italic? + /// @param characters Characters in this style /// @return Path to the matching font file(s), or empty if not found - virtual std::vector GetFontPaths(wxString const& facename, int bold, bool italic) = 0; + virtual std::vector GetFontPaths(wxString const& facename, int bold, bool italic, std::set const& characters) = 0; }; /// @class FontCollector @@ -65,8 +66,8 @@ class FontCollector { /// The actual lister to use to get font paths FontFileLister &lister; - /// A set of each combination of styles used in the file - std::set used_styles; + /// The set of all glyphs used in the file + std::map > used_styles; /// Style name -> ASS style definition std::map styles; /// Paths to found required font files @@ -77,7 +78,7 @@ class FontCollector { /// Gather all of the unique styles with text on a line void ProcessDialogueLine(AssDialogue *line); /// Get the font for a single style - void ProcessChunk(StyleInfo const& style); + void ProcessChunk(std::pair > const& style); public: /// Constructor diff --git a/aegisub/src/font_file_lister_fontconfig.cpp b/aegisub/src/font_file_lister_fontconfig.cpp index 993307688..24d43a464 100644 --- a/aegisub/src/font_file_lister_fontconfig.cpp +++ b/aegisub/src/font_file_lister_fontconfig.cpp @@ -71,6 +71,7 @@ namespace { FontConfigFontFileLister::FontConfigFontFileLister(FontCollectorStatusCallback cb) : config(FcInitLoadConfig(), FcConfigDestroy) +, cb(cb) { cb(_("Updating font cache\n"), 0); FcConfigBuildFonts(config); @@ -112,7 +113,7 @@ FcFontSet *FontConfigFontFileLister::MatchFullname(const char *family, int weigh return result; } -std::vector FontConfigFontFileLister::GetFontPaths(wxString const& facename, int bold, bool italic) { +std::vector FontConfigFontFileLister::GetFontPaths(wxString const& facename, int bold, bool italic, std::set const& characters) { std::vector ret; std::string family = STD_STR(facename); @@ -187,6 +188,21 @@ std::vector FontConfigFontFileLister::GetFontPaths(wxString const& fac if(FcPatternGetString(rpat, FC_FILE, 0, &file) != FcResultMatch) return ret; + wxString missing; + + FcCharSet *charset; + if (FcPatternGetCharSet(rpat, FC_CHARSET, 0, &charset) == FcResultMatch) { + for (std::set::const_iterator it = characters.begin(); it != characters.end(); ++it) { + if (!FcCharSetHasChar(charset, *it)) + missing += *it; + } + } + + if (missing.size() > 50) + cb(wxString::Format(_("'%s' is missing %d glyphs used.\n"), facename, (int)missing.size()), 2); + else if (missing.size() > 0) + cb(wxString::Format(_("'%s' is missing the following glyphs used: %s\n"), facename, missing), 2); + ret.push_back((const char *)file); return ret; } diff --git a/aegisub/src/font_file_lister_fontconfig.h b/aegisub/src/font_file_lister_fontconfig.h index 516ce5811..ce7e2963d 100644 --- a/aegisub/src/font_file_lister_fontconfig.h +++ b/aegisub/src/font_file_lister_fontconfig.h @@ -42,6 +42,7 @@ class FontConfigFontFileLister : public FontFileLister { }; scoped config; + FontCollectorStatusCallback cb; /// @brief Case-insensitive match ASS/SSA font family against full name. (also known as "name for humans") /// @param family font fullname @@ -54,7 +55,7 @@ public: /// @param cb Callback for status logging FontConfigFontFileLister(FontCollectorStatusCallback cb); - std::vector GetFontPaths(wxString const& facename, int bold, bool italic); + std::vector GetFontPaths(wxString const& facename, int bold, bool italic, std::set const& characters); }; #endif diff --git a/aegisub/src/font_file_lister_freetype.cpp b/aegisub/src/font_file_lister_freetype.cpp index d10a6d527..82d2a64d8 100644 --- a/aegisub/src/font_file_lister_freetype.cpp +++ b/aegisub/src/font_file_lister_freetype.cpp @@ -171,7 +171,7 @@ void FreetypeFontFileLister::AddFont(wxString const& filename, wxString const& f AddFont(filename, "*" + family); } -std::vector FreetypeFontFileLister::GetFontPaths(wxString const& facename, int, bool) { +std::vector FreetypeFontFileLister::GetFontPaths(wxString const& facename, int, bool, std::set const&) { std::vector ret; ret.insert(ret.end(), font_files[facename].begin(), font_files[facename].end()); if (ret.empty()) diff --git a/aegisub/src/font_file_lister_freetype.h b/aegisub/src/font_file_lister_freetype.h index e651afffd..ac3748081 100644 --- a/aegisub/src/font_file_lister_freetype.h +++ b/aegisub/src/font_file_lister_freetype.h @@ -57,7 +57,7 @@ public: /// @param cb Callback for status logging FreetypeFontFileLister(FontCollectorStatusCallback cb); - std::vector GetFontPaths(wxString const& facename, int, bool); + std::vector GetFontPaths(wxString const& facename, int, bool, std::set const&); }; #endif