Remove some cruft from the fonts collector

This commit is contained in:
Thomas Goyne 2014-07-05 10:31:53 -07:00
parent e924db1fda
commit dd70da35d4
7 changed files with 108 additions and 143 deletions

View file

@ -157,7 +157,6 @@
<ClInclude Include="$(SrcDir)ffmpegsource_common.h" />
<ClInclude Include="$(SrcDir)fft.h" />
<ClInclude Include="$(SrcDir)font_file_lister.h" />
<ClInclude Include="$(SrcDir)font_file_lister_fontconfig.h" />
<ClInclude Include="$(SrcDir)frame_main.h" />
<ClInclude Include="$(SrcDir)gl_text.h" />
<ClInclude Include="$(SrcDir)gl_wrap.h" />

View file

@ -225,9 +225,6 @@
<ClInclude Include="$(SrcDir)font_file_lister.h">
<Filter>Features\Font collector</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)font_file_lister_fontconfig.h">
<Filter>Features\Font collector</Filter>
</ClInclude>
<ClInclude Include="$(SrcDir)dialog_detached_video.h">
<Filter>Video\UI</Filter>
</ClInclude>
@ -1117,4 +1114,4 @@
<ResourceCompile Include="$(SrcDir)res\res.rc" />
<ResourceCompile Include="$(SrcDir)res\strings.rc" />
</ItemGroup>
</Project>
</Project>

View file

@ -15,7 +15,6 @@
// Aegisub Project http://www.aegisub.org/
#include "font_file_lister.h"
#include "font_file_lister_fontconfig.h"
#include "compat.h"
#include "dialog_manager.h"
@ -91,8 +90,7 @@ void FontsCollectorThread(AssFile *subs, agi::fs::path const& destination, FcMod
collector->AddPendingEvent(event);
};
FontConfigFontFileLister lister(AppendText);
auto paths = FontCollector(AppendText, lister).GetFontPaths(subs);
auto paths = FontCollector(AppendText).GetFontPaths(subs);
if (paths.empty()) {
collector->AddPendingEvent(wxThreadEvent(EVT_COLLECTION_DONE));
return;

View file

@ -14,11 +14,6 @@
//
// Aegisub Project http://www.aegisub.org/
/// @file font_file_lister.cpp
/// @brief Base-class for font collector implementations
/// @ingroup font_collector
///
#include "font_file_lister.h"
#include "ass_dialogue.h"
@ -36,31 +31,31 @@
#include <wx/intl.h>
namespace {
wxString format_missing(wxString const& str) {
wxString printable;
wxString unprintable;
for (wxUniChar c : str) {
if (!u_isUWhiteSpace(c.GetValue()))
printable += c;
else {
unprintable += fmt_wx("\n - U+%04X ", c.GetValue());
UErrorCode ec;
char buf[1024];
auto len = u_charName(c.GetValue(), U_EXTENDED_CHAR_NAME, buf, sizeof buf, &ec);
if (len != 0 && U_SUCCESS(ec))
unprintable += to_wx(buf);
if (c.GetValue() == 0xA0)
unprintable += " (\\h)";
}
wxString format_missing(wxString const& str) {
wxString printable;
wxString unprintable;
for (wxUniChar c : str) {
if (!u_isUWhiteSpace(c.GetValue()))
printable += c;
else {
unprintable += fmt_wx("\n - U+%04X ", c.GetValue());
UErrorCode ec;
char buf[1024];
auto len = u_charName(c.GetValue(), U_EXTENDED_CHAR_NAME, buf, sizeof buf, &ec);
if (len != 0 && U_SUCCESS(ec))
unprintable += to_wx(buf);
if (c.GetValue() == 0xA0)
unprintable += " (\\h)";
}
return printable + unprintable;
}
return printable + unprintable;
}
}
FontCollector::FontCollector(FontCollectorStatusCallback status_callback, FontFileLister &lister)
FontCollector::FontCollector(FontCollectorStatusCallback status_callback)
: status_callback(std::move(status_callback))
, lister(lister)
, lister(this->status_callback)
{
}
@ -80,50 +75,66 @@ void FontCollector::ProcessDialogueLine(const AssDialogue *line, int index) {
bool overriden = false;
for (auto& block : line->ParseTags()) {
if (AssDialogueBlockOverride *ovr = dynamic_cast<AssDialogueBlockOverride *>(block.get())) {
if (auto ovr = dynamic_cast<AssDialogueBlockOverride *>(block.get())) {
for (auto const& tag : ovr->Tags) {
std::string const& name = tag.Name;
if (name == "\\r") {
if (tag.Name == "\\r") {
style = styles[tag.Params[0].Get(line->Style.get())];
overriden = false;
}
else if (name == "\\b") {
else if (tag.Name == "\\b") {
style.bold = tag.Params[0].Get(initial.bold);
overriden = true;
}
else if (name == "\\i") {
else if (tag.Name == "\\i") {
style.italic = tag.Params[0].Get(initial.italic);
overriden = true;
}
else if (name == "\\fn") {
else if (tag.Name == "\\fn") {
style.facename = tag.Params[0].Get(initial.facename);
overriden = true;
}
}
}
else if (AssDialogueBlockPlain *txt = dynamic_cast<AssDialogueBlockPlain *>(block.get())) {
wxString text(to_wx(txt->GetText()));
else if (auto txt = dynamic_cast<AssDialogueBlockPlain *>(block.get())) {
auto text = txt->GetText();
if (text.empty())
continue;
if (overriden)
used_styles[style].lines.insert(index);
std::set<wxUniChar>& chars = used_styles[style].chars;
for (auto it = text.begin(); it != text.end(); ++it) {
wxUniChar cur = *it;
if (cur == L'\\' && it + 1 != text.end()) {
wxUniChar next = *++it;
if (next == 'N' || next == 'n')
continue;
if (next == 'h')
cur = 0xA0;
else
--it;
}
chars.insert(cur);
auto& usage = used_styles[style];
if (overriden) {
auto& lines = usage.lines;
if (lines.empty() || lines.back() != index)
lines.push_back(index);
}
auto& chars = usage.chars;
auto size = static_cast<int>(text.size());
for (int i = 0; i < size; ) {
if (text[i] == '\\' && i + 1 < size) {
char next = text[++i];
if (next == 'N' || next == 'n') {
++i;
continue;
}
if (next == 'h') {
++i;
chars.push_back(0xA0);
continue;
}
chars.push_back('\\');
continue;
}
UChar32 c;
U8_NEXT(&text[0], i, size, c);
chars.push_back(c);
}
sort(begin(chars), end(chars));
chars.erase(unique(chars.begin(), chars.end()), chars.end());
}
// Do nothing with drawing and comment blocks
}
@ -132,7 +143,7 @@ void FontCollector::ProcessDialogueLine(const AssDialogue *line, int index) {
void FontCollector::ProcessChunk(std::pair<StyleInfo, UsageData> const& style) {
if (style.second.chars.empty()) return;
FontFileLister::CollectionResult res = lister.GetFontPaths(style.first.facename, style.first.bold, style.first.italic, style.second.chars);
auto res = lister.GetFontPaths(style.first.facename, style.first.bold, style.first.italic, style.second.chars);
if (res.paths.empty()) {
status_callback(fmt_tl("Could not find font '%s'\n", style.first.facename), 2);
@ -141,8 +152,11 @@ void FontCollector::ProcessChunk(std::pair<StyleInfo, UsageData> const& style) {
}
else {
for (auto& elem : res.paths) {
if (results.insert(elem).second)
status_callback(fmt_tl("Found '%s' at '%s'\n", style.first.facename, elem.make_preferred()), 0);
elem.make_preferred();
if (std::find(begin(results), end(results), elem) == end(results)) {
status_callback(fmt_tl("Found '%s' at '%s'\n", style.first.facename, elem), 0);
results.push_back(elem);
}
}
if (res.fake_bold)
@ -190,7 +204,7 @@ std::vector<agi::fs::path> FontCollector::GetFontPaths(const AssFile *file) {
info.facename = style.font;
info.bold = style.bold;
info.italic = style.italic;
used_styles[info].styles.insert(style.name);
used_styles[info].styles.push_back(style.name);
}
int index = 0;

View file

@ -14,19 +14,12 @@
//
// Aegisub Project http://www.aegisub.org/
/// @file font_file_lister.h
/// @see font_file_lister.cpp
/// @ingroup font_collector
///
#pragma once
#include <libaegisub/fs_fwd.h>
#include <libaegisub/scoped_ptr.h>
#include <boost/filesystem/path.hpp>
#include <functional>
#include <map>
#include <set>
#include <string>
#include <vector>
@ -37,18 +30,33 @@ class AssFile;
typedef std::function<void (wxString, int)> FontCollectorStatusCallback;
/// @class FontFileLister
/// @brief Font lister interface
class FontFileLister {
struct CollectionResult {
/// Characters which could not be found in any font files
wxString missing;
/// Paths to the file(s) containing the requested font
std::vector<agi::fs::path> paths;
bool fake_bold = false;
bool fake_italic = false;
};
typedef struct _FcConfig FcConfig;
typedef struct _FcFontSet FcFontSet;
/// @class FontConfigFontFileLister
/// @brief fontconfig powered font lister
class FontConfigFontFileLister {
agi::scoped_holder<FcConfig*> config;
/// @brief Case-insensitive match ASS/SSA font family against full name. (also known as "name for humans")
/// @param family font fullname
/// @param bold weight attribute
/// @param italic italic attribute
/// @return font set
FcFontSet *MatchFullname(const char *family, int weight, int slant);
public:
struct CollectionResult {
/// Characters which could not be found in any font files
wxString missing;
/// Paths to the file(s) containing the requested font
std::vector<agi::fs::path> paths;
bool fake_bold = false;
bool fake_italic = false;
};
/// Constructor
/// @param cb Callback for status logging
FontConfigFontFileLister(FontCollectorStatusCallback &cb);
/// @brief Get the path to the font with the given styles
/// @param facename Name of font face
@ -56,7 +64,7 @@ public:
/// @param italic Italic?
/// @param characters Characters in this style
/// @return Path to the matching font file(s), or empty if not found
virtual CollectionResult GetFontPaths(std::string const& facename, int bold, bool italic, std::set<wxUniChar> const& characters) = 0;
CollectionResult GetFontPaths(std::string const& facename, int bold, bool italic, std::vector<int> const& characters);
};
/// @class FontCollector
@ -72,22 +80,22 @@ class FontCollector {
/// Data about where each style is used
struct UsageData {
std::set<wxUniChar> chars; ///< Characters used in this style which glyphs will be needed for
std::set<int> lines; ///< Lines on which this style is used via overrides
std::set<std::string> styles; ///< ASS styles which use this style
std::vector<int> chars; ///< Characters used in this style which glyphs will be needed for
std::vector<int> lines; ///< Lines on which this style is used via overrides
std::vector<std::string> styles; ///< ASS styles which use this style
};
/// Message callback provider by caller
FontCollectorStatusCallback status_callback;
/// The actual lister to use to get font paths
FontFileLister &lister;
FontConfigFontFileLister lister;
/// The set of all glyphs used in the file
std::map<StyleInfo, UsageData> used_styles;
/// Style name -> ASS style definition
std::map<std::string, StyleInfo> styles;
/// Paths to found required font files
std::set<agi::fs::path> results;
std::vector<agi::fs::path> results;
/// Number of fonts which could not be found
int missing = 0;
/// Number of fonts which were found, but did not contain all used glyphs
@ -106,7 +114,7 @@ public:
/// Constructor
/// @param status_callback Function to pass status updates to
/// @param lister The actual font file lister
FontCollector(FontCollectorStatusCallback status_callback, FontFileLister &lister);
FontCollector(FontCollectorStatusCallback status_callback);
/// @brief Get a list of the locations of all font files used in the file
/// @param file Lines in the subtitle file to check

View file

@ -14,12 +14,7 @@
//
// Aegisub Project http://www.aegisub.org/
/// @file font_file_lister_fontconfig.cpp
/// @brief Font Config-based font collector
/// @ingroup font_collector
///
#include "font_file_lister_fontconfig.h"
#include "font_file_lister.h"
#include <libaegisub/log.h>
@ -74,14 +69,14 @@ void find_font(FcFontSet *src, FcFontSet *dst, std::string const& family) {
}
FontConfigFontFileLister::FontConfigFontFileLister(FontCollectorStatusCallback cb)
FontConfigFontFileLister::FontConfigFontFileLister(FontCollectorStatusCallback &cb)
: config(init_fontconfig(), FcConfigDestroy)
{
cb(_("Updating font cache\n"), 0);
FcConfigBuildFonts(config);
}
FontFileLister::CollectionResult FontConfigFontFileLister::GetFontPaths(std::string const& facename, int bold, bool italic, std::set<wxUniChar> const& characters) {
CollectionResult FontConfigFontFileLister::GetFontPaths(std::string const& facename, int bold, bool italic, std::vector<int> const& characters) {
CollectionResult ret;
std::string family = facename[0] == '@' ? facename.substr(1) : facename;
@ -124,7 +119,7 @@ FontFileLister::CollectionResult FontConfigFontFileLister::GetFontPaths(std::str
FcCharSet *charset;
if (FcPatternGetCharSet(match, FC_CHARSET, 0, &charset) == FcResultMatch) {
for (wxUniChar chr : characters) {
for (int chr : characters) {
if (!FcCharSetHasChar(charset, chr))
ret.missing += chr;
}

View file

@ -1,46 +0,0 @@
// Copyright (c) 2012, Thomas Goyne <plorkyeran@aegisub.org>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Aegisub Project http://www.aegisub.org/
/// @file font_file_lister_fontconfig.h
/// @see font_file_lister_fontconfig.cpp
/// @ingroup font_collector
///
#include "font_file_lister.h"
#include <libaegisub/scoped_ptr.h>
typedef struct _FcConfig FcConfig;
typedef struct _FcFontSet FcFontSet;
/// @class FontConfigFontFileLister
/// @brief fontconfig powered font lister
class FontConfigFontFileLister final : public FontFileLister {
agi::scoped_holder<FcConfig*> config;
/// @brief Case-insensitive match ASS/SSA font family against full name. (also known as "name for humans")
/// @param family font fullname
/// @param bold weight attribute
/// @param italic italic attribute
/// @return font set
FcFontSet *MatchFullname(const char *family, int weight, int slant);
public:
/// Constructor
/// @param cb Callback for status logging
FontConfigFontFileLister(FontCollectorStatusCallback cb);
CollectionResult GetFontPaths(std::string const& facename, int bold, bool italic, std::set<wxUniChar> const& characters) override;
};