1 // Copyright (c) 2012, Thomas Goyne <plorkyeran@aegisub.org> 2 // 3 // Permission to use, copy, modify, and distribute this software for any 4 // purpose with or without fee is hereby granted, provided that the above 5 // copyright notice and this permission notice appear in all copies. 6 // 7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 // 15 // Aegisub Project http://www.aegisub.org/ 16 17 #include <libaegisub/fs_fwd.h> 18 #include <libaegisub/scoped_ptr.h> 19 20 #include <boost/filesystem/path.hpp> 21 #include <functional> 22 #include <map> 23 #include <string> 24 #include <vector> 25 26 #include <wx/string.h> 27 28 class AssDialogue; 29 class AssFile; 30 31 typedef std::function<void (wxString, int)> FontCollectorStatusCallback; 32 33 struct CollectionResult { 34 /// Characters which could not be found in any font files 35 wxString missing; 36 /// Paths to the file(s) containing the requested font 37 std::vector<agi::fs::path> paths; 38 bool fake_bold = false; 39 bool fake_italic = false; 40 }; 41 42 typedef struct _FcConfig FcConfig; 43 typedef struct _FcFontSet FcFontSet; 44 45 /// @class FontConfigFontFileLister 46 /// @brief fontconfig powered font lister 47 class FontConfigFontFileLister { 48 agi::scoped_holder<FcConfig*> config; 49 50 /// @brief Case-insensitive match ASS/SSA font family against full name. (also known as "name for humans") 51 /// @param family font fullname 52 /// @param bold weight attribute 53 /// @param italic italic attribute 54 /// @return font set 55 FcFontSet *MatchFullname(const char *family, int weight, int slant); 56 public: 57 /// Constructor 58 /// @param cb Callback for status logging 59 FontConfigFontFileLister(FontCollectorStatusCallback &cb); 60 61 /// @brief Get the path to the font with the given styles 62 /// @param facename Name of font face 63 /// @param bold ASS font weight 64 /// @param italic Italic? 65 /// @param characters Characters in this style 66 /// @return Path to the matching font file(s), or empty if not found 67 CollectionResult GetFontPaths(std::string const& facename, int bold, bool italic, std::vector<int> const& characters); 68 }; 69 70 /// @class FontCollector 71 /// @brief Class which collects the paths to all fonts used in a script 72 class FontCollector { 73 /// All data needed to find the font file used to render text 74 struct StyleInfo { 75 std::string facename; 76 int bold; 77 bool italic; 78 bool operator<(StyleInfo const& rgt) const; 79 }; 80 81 /// Data about where each style is used 82 struct UsageData { 83 std::vector<int> chars; ///< Characters used in this style which glyphs will be needed for 84 std::vector<int> lines; ///< Lines on which this style is used via overrides 85 std::vector<std::string> styles; ///< ASS styles which use this style 86 }; 87 88 /// Message callback provider by caller 89 FontCollectorStatusCallback status_callback; 90 91 FontConfigFontFileLister lister; 92 93 /// The set of all glyphs used in the file 94 std::map<StyleInfo, UsageData> used_styles; 95 /// Style name -> ASS style definition 96 std::map<std::string, StyleInfo> styles; 97 /// Paths to found required font files 98 std::vector<agi::fs::path> results; 99 /// Number of fonts which could not be found 100 int missing = 0; 101 /// Number of fonts which were found, but did not contain all used glyphs 102 int missing_glyphs = 0; 103 104 /// Gather all of the unique styles with text on a line 105 void ProcessDialogueLine(const AssDialogue *line, int index); 106 107 /// Get the font for a single style 108 void ProcessChunk(std::pair<StyleInfo, UsageData> const& style); 109 110 /// Print the lines and styles on which a missing font is used 111 void PrintUsage(UsageData const& data); 112 113 public: 114 /// Constructor 115 /// @param status_callback Function to pass status updates to 116 /// @param lister The actual font file lister 117 FontCollector(FontCollectorStatusCallback status_callback); 118 119 /// @brief Get a list of the locations of all font files used in the file 120 /// @param file Lines in the subtitle file to check 121 /// @param status Callback function for messages 122 /// @return List of paths to fonts 123 std::vector<agi::fs::path> GetFontPaths(const AssFile *file); 124 }; 125