2012-01-12 23:32:09 +01:00
|
|
|
// Copyright (c) 2012, Thomas Goyne <plorkyeran@aegisub.org>
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2012-01-12 23:32:09 +01:00
|
|
|
// 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.
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2012-01-12 23:32:09 +01:00
|
|
|
// 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.
|
2006-01-16 22:02:54 +01:00
|
|
|
//
|
2009-07-29 07:43:02 +02:00
|
|
|
// Aegisub Project http://www.aegisub.org/
|
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
#include "font_file_lister.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
|
2010-05-21 03:13:36 +02:00
|
|
|
#include "compat.h"
|
2014-05-22 21:07:15 +02:00
|
|
|
#include "dialog_manager.h"
|
2014-05-29 17:28:37 +02:00
|
|
|
#include "format.h"
|
2008-01-13 23:25:26 +01:00
|
|
|
#include "help_button.h"
|
2012-03-09 01:24:01 +01:00
|
|
|
#include "include/aegisub/context.h"
|
2009-07-24 02:08:25 +02:00
|
|
|
#include "libresrc/libresrc.h"
|
2013-01-07 02:50:09 +01:00
|
|
|
#include "options.h"
|
2009-09-10 15:06:40 +02:00
|
|
|
#include "utils.h"
|
2015-01-01 17:12:05 +01:00
|
|
|
#include "value_event.h"
|
2007-06-20 07:18:47 +02:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
#include <libaegisub/dispatch.h>
|
2014-05-29 17:28:37 +02:00
|
|
|
#include <libaegisub/format_path.h>
|
2013-01-04 16:01:50 +01:00
|
|
|
#include <libaegisub/fs.h>
|
2013-01-30 04:35:37 +01:00
|
|
|
#include <libaegisub/path.h>
|
2014-04-23 22:53:24 +02:00
|
|
|
#include <libaegisub/make_unique.h>
|
2012-01-12 23:32:09 +01:00
|
|
|
|
|
|
|
#include <wx/button.h>
|
2014-05-22 21:07:15 +02:00
|
|
|
#include <wx/dialog.h>
|
2012-01-12 23:32:09 +01:00
|
|
|
#include <wx/dirdlg.h>
|
|
|
|
#include <wx/filedlg.h>
|
|
|
|
#include <wx/filename.h>
|
|
|
|
#include <wx/msgdlg.h>
|
|
|
|
#include <wx/radiobox.h>
|
|
|
|
#include <wx/sizer.h>
|
|
|
|
#include <wx/statbox.h>
|
|
|
|
#include <wx/stattext.h>
|
|
|
|
#include <wx/stc/stc.h>
|
|
|
|
#include <wx/textctrl.h>
|
|
|
|
#include <wx/wfstream.h>
|
|
|
|
#include <wx/zipstrm.h>
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2014-05-22 21:07:15 +02:00
|
|
|
namespace {
|
2015-11-01 05:12:24 +01:00
|
|
|
enum class FcMode {
|
|
|
|
CheckFontsOnly = 0,
|
|
|
|
CopyToFolder = 1,
|
|
|
|
CopyToScriptFolder = 2,
|
|
|
|
CopyToZip = 3,
|
|
|
|
SymlinkToFolder = 4
|
|
|
|
};
|
|
|
|
|
2014-05-22 21:07:15 +02:00
|
|
|
class DialogFontsCollector final : public wxDialog {
|
|
|
|
AssFile *subs;
|
2015-08-22 03:17:48 +02:00
|
|
|
agi::Path &path;
|
2015-11-01 05:12:24 +01:00
|
|
|
FcMode mode = FcMode::CheckFontsOnly;
|
2014-05-22 21:07:15 +02:00
|
|
|
|
2014-05-30 21:39:39 +02:00
|
|
|
wxStyledTextCtrl *collection_log;
|
2014-05-22 21:07:15 +02:00
|
|
|
wxButton *close_btn;
|
|
|
|
wxButton *dest_browse_button;
|
|
|
|
wxButton *start_btn;
|
|
|
|
wxRadioBox *collection_mode;
|
|
|
|
wxStaticText *dest_label;
|
|
|
|
wxTextCtrl *dest_ctrl;
|
|
|
|
|
|
|
|
void OnStart(wxCommandEvent &);
|
|
|
|
void OnBrowse(wxCommandEvent &);
|
|
|
|
void OnRadio(wxCommandEvent &e);
|
|
|
|
|
|
|
|
/// Append text to log message from worker thread
|
2015-01-01 17:12:05 +01:00
|
|
|
void OnAddText(ValueEvent<std::pair<int, wxString>>& event);
|
2014-05-22 21:07:15 +02:00
|
|
|
/// Collection complete notification from the worker thread to reenable buttons
|
|
|
|
void OnCollectionComplete(wxThreadEvent &);
|
|
|
|
|
2015-11-03 05:12:32 +01:00
|
|
|
void UpdateControls();
|
|
|
|
|
2014-05-22 21:07:15 +02:00
|
|
|
public:
|
|
|
|
DialogFontsCollector(agi::Context *c);
|
|
|
|
};
|
|
|
|
|
2015-01-01 17:12:05 +01:00
|
|
|
using color_str_pair = std::pair<int, wxString>;
|
|
|
|
wxDEFINE_EVENT(EVT_ADD_TEXT, ValueEvent<color_str_pair>);
|
2012-01-12 23:32:09 +01:00
|
|
|
wxDEFINE_EVENT(EVT_COLLECTION_DONE, wxThreadEvent);
|
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
void FontsCollectorThread(AssFile *subs, agi::fs::path const& destination, FcMode oper, wxEvtHandler *collector) {
|
|
|
|
agi::dispatch::Background().Async([=]{
|
|
|
|
auto AppendText = [&](wxString text, int colour) {
|
2015-01-01 17:12:05 +01:00
|
|
|
collector->AddPendingEvent(ValueEvent<color_str_pair>(EVT_ADD_TEXT, -1, {colour, text.Clone()}));
|
2013-01-04 16:01:50 +01:00
|
|
|
};
|
2012-01-12 23:32:09 +01:00
|
|
|
|
Rework Windows font collector (arch1t3cht/Aegisub#107)
[src\meson.build] Add DirectWrite has dependency
[src\font_file_lister_gdi] Rework GDI FontCollector to use DirectWrite
This replaces all the logic of using the Windows registry to obtain the font path by using DirectWrite. The goal is simply to improve the quality of the code. This doesn't change any functionality
[src\meson.build] Remove Uniscribe has dependency
Uniscribe was only used for the FontCollector. Since we now use DirectWrite, we don't need it anymore.
[src\dialog_fonts_collector] Catch exceptions that FontCollector may raise
On Windows, the initialization of the FontCollector can raise an exception
[src\font_file_lister] Document the exception that GdiFontFileLister can throw
[src\font_file_lister_gdi] Correct possible memory leak when an error occur
Fix error caused by AddFontResource on Windows 10 or higher
[meson.build] Replace add_project_arguments with conf.set for HAVE_DWRITE_3
[src\dialog_fonts_collector] Update message error and optimisation
[src\font_file_lister_gdi] Correct documentation typo
[src\font_file_lister_gdi] Cosmetic nit - Initialize hfont in one line
[src\font_file_lister_gdi] Cosmetic nit - Remove if statements brace
[src\font_file_lister_gdi] Replace WCHAR param of normalizeFilePathCase to std::wstring
[src\font_file_lister_gdi] Replace WCHAR by std::wstring
[src\font_file_lister_gdi] Use IDWriteFontFace::GetSimulations to detect fake_italic/fake_bold
See this comment: https://github.com/arch1t3cht/Aegisub/pull/107#issuecomment-1975229652
[src\font_file_lister_gdi] If Win7/8 has Win 10 SDK on compile time, correctly verify if font has character(s)
With the Visual Studio 2019 toolchain on Windows 7, it installs the Windows 10 SDK by default. Because of this, ``HAVE_DWRITE_3`` is true, so the ``QueryInterface`` always fails. Now, if the ``QueryInterface`` fails, we try to verify if the font has characters with a Windows Vista SP2 compatible code.
[src\font_file_lister_gdi] Support facename that contains only whitespace AND truncated facename
Problem 1:
Previously, if a user wrote "\fn ", it would return the font Arial, which is not what we want. This is because when we request EnumFontFamiliesEx with whitespace or an empty lfFaceName, it will enumerate all the installed fonts.
Solution 1:
To resolve this issue, let's implement a solution similar to libass to determine if the selected facename exists: https://github.com/libass/libass/blob/649a7c2e1fc6f4188ea1a89968560715800b883d/libass/ass_directwrite.c#L737-L747
Problem 2:
GDI truncates font names to 31 characters. See: https://github.com/libass/libass/issues/459
However, since I changed the method to determine if a facename exists, I ensured that we still support this "feature".
To test this, I used the font in: https://github.com/libass/libass/issues/710
[src\font_file_lister_gdi] Add a FIXME comment regarding the utilization of std::wstring over WCHAR
[src\font_file_lister_gdi] Add FIXME comment about charset
2024-02-01 02:48:34 +01:00
|
|
|
std::vector<agi::fs::path> paths;
|
|
|
|
try {
|
|
|
|
paths = FontCollector(AppendText).GetFontPaths(subs);
|
|
|
|
}
|
|
|
|
catch (agi::EnvironmentError const& err) {
|
|
|
|
AppendText(fmt_tl("* An error occurred when enumerating the used fonts: %s.\n", err.GetMessage()), 2);
|
|
|
|
}
|
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
if (paths.empty()) {
|
|
|
|
collector->AddPendingEvent(wxThreadEvent(EVT_COLLECTION_DONE));
|
|
|
|
return;
|
|
|
|
}
|
2012-01-12 23:32:09 +01:00
|
|
|
|
|
|
|
// Copy fonts
|
|
|
|
switch (oper) {
|
2015-11-01 05:12:24 +01:00
|
|
|
case FcMode::CheckFontsOnly:
|
2013-01-04 16:01:50 +01:00
|
|
|
collector->AddPendingEvent(wxThreadEvent(EVT_COLLECTION_DONE));
|
2012-05-10 16:18:47 +02:00
|
|
|
return;
|
2015-11-01 05:12:24 +01:00
|
|
|
case FcMode::SymlinkToFolder:
|
2013-01-04 16:01:50 +01:00
|
|
|
AppendText(_("Symlinking fonts to folder...\n"), 0);
|
2012-05-10 16:18:47 +02:00
|
|
|
break;
|
2015-11-01 05:12:24 +01:00
|
|
|
case FcMode::CopyToScriptFolder:
|
|
|
|
case FcMode::CopyToFolder:
|
2013-01-04 16:01:50 +01:00
|
|
|
AppendText(_("Copying fonts to folder...\n"), 0);
|
2012-05-10 16:18:47 +02:00
|
|
|
break;
|
2015-11-01 05:12:24 +01:00
|
|
|
case FcMode::CopyToZip:
|
2013-01-04 16:01:50 +01:00
|
|
|
AppendText(_("Copying fonts to archive...\n"), 0);
|
2012-05-10 16:18:47 +02:00
|
|
|
break;
|
2012-01-12 23:32:09 +01:00
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
// Open zip stream if saving to compressed archive
|
2013-01-04 16:01:50 +01:00
|
|
|
std::unique_ptr<wxFFileOutputStream> out;
|
|
|
|
std::unique_ptr<wxZipOutputStream> zip;
|
2015-11-01 05:12:24 +01:00
|
|
|
if (oper == FcMode::CopyToZip) {
|
2014-04-20 15:42:04 +02:00
|
|
|
try {
|
|
|
|
agi::fs::CreateDirectory(destination.parent_path());
|
|
|
|
}
|
|
|
|
catch (agi::fs::FileSystemError const& e) {
|
2014-05-29 17:28:37 +02:00
|
|
|
AppendText(fmt_tl("* Failed to create directory '%s': %s.\n",
|
2014-05-29 14:57:27 +02:00
|
|
|
destination.parent_path().wstring(), to_wx(e.GetMessage())), 2);
|
2014-04-20 15:42:04 +02:00
|
|
|
collector->AddPendingEvent(wxThreadEvent(EVT_COLLECTION_DONE));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-04-23 22:53:24 +02:00
|
|
|
out = agi::make_unique<wxFFileOutputStream>(destination.wstring());
|
2014-04-20 05:04:02 +02:00
|
|
|
if (out->IsOk())
|
2014-04-23 22:53:24 +02:00
|
|
|
zip = agi::make_unique<wxZipOutputStream>(*out);
|
2014-04-20 15:42:04 +02:00
|
|
|
|
2014-04-20 05:04:02 +02:00
|
|
|
if (!out->IsOk() || !zip || !zip->IsOk()) {
|
2014-05-29 17:28:37 +02:00
|
|
|
AppendText(fmt_tl("* Failed to open %s.\n", destination), 2);
|
2014-04-20 05:04:02 +02:00
|
|
|
collector->AddPendingEvent(wxThreadEvent(EVT_COLLECTION_DONE));
|
|
|
|
return;
|
|
|
|
}
|
2012-01-12 23:32:09 +01:00
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2012-04-08 04:28:43 +02:00
|
|
|
int64_t total_size = 0;
|
2012-01-12 23:32:09 +01:00
|
|
|
bool allOk = true;
|
2013-01-04 16:01:50 +01:00
|
|
|
for (auto path : paths) {
|
|
|
|
path.make_preferred();
|
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
int ret = 0;
|
2013-01-04 16:01:50 +01:00
|
|
|
total_size += agi::fs::Size(path);
|
2012-04-08 04:28:43 +02:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
switch (oper) {
|
2015-11-01 05:12:24 +01:00
|
|
|
case FcMode::SymlinkToFolder:
|
|
|
|
case FcMode::CopyToScriptFolder:
|
|
|
|
case FcMode::CopyToFolder: {
|
2013-01-04 16:01:50 +01:00
|
|
|
auto dest = destination/path.filename();
|
|
|
|
if (agi::fs::FileExists(dest))
|
2012-01-12 23:32:09 +01:00
|
|
|
ret = 2;
|
2012-05-10 16:18:47 +02:00
|
|
|
#ifndef _WIN32
|
2015-11-01 05:12:24 +01:00
|
|
|
else if (oper == FcMode::SymlinkToFolder) {
|
2012-05-10 16:18:47 +02:00
|
|
|
// returns 0 on success, -1 on error...
|
2013-01-04 16:01:50 +01:00
|
|
|
if (symlink(path.c_str(), dest.c_str()))
|
2012-05-10 16:18:47 +02:00
|
|
|
ret = 0;
|
|
|
|
else
|
|
|
|
ret = 3;
|
|
|
|
}
|
|
|
|
#endif
|
2013-01-04 16:01:50 +01:00
|
|
|
else {
|
|
|
|
try {
|
|
|
|
agi::fs::Copy(path, dest);
|
|
|
|
ret = true;
|
|
|
|
}
|
|
|
|
catch (...) {
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
}
|
2012-01-12 23:32:09 +01:00
|
|
|
}
|
|
|
|
break;
|
2012-05-10 16:18:47 +02:00
|
|
|
|
2015-11-01 05:12:24 +01:00
|
|
|
case FcMode::CopyToZip: {
|
2013-01-04 16:01:50 +01:00
|
|
|
wxFFileInputStream in(path.wstring());
|
2012-01-12 23:32:09 +01:00
|
|
|
if (!in.IsOk())
|
|
|
|
ret = false;
|
|
|
|
else {
|
2013-01-04 16:01:50 +01:00
|
|
|
ret = zip->PutNextEntry(path.filename().wstring());
|
2012-01-12 23:32:09 +01:00
|
|
|
zip->Write(in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
default: break;
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
if (ret == 1)
|
2014-05-29 17:28:37 +02:00
|
|
|
AppendText(fmt_tl("* Copied %s.\n", path), 1);
|
2012-01-12 23:32:09 +01:00
|
|
|
else if (ret == 2)
|
2014-05-29 17:28:37 +02:00
|
|
|
AppendText(fmt_tl("* %s already exists on destination.\n", path.filename()), 3);
|
2012-05-10 16:18:47 +02:00
|
|
|
else if (ret == 3)
|
2014-05-29 17:28:37 +02:00
|
|
|
AppendText(fmt_tl("* Symlinked %s.\n", path), 1);
|
2012-01-12 23:32:09 +01:00
|
|
|
else {
|
2014-05-29 17:28:37 +02:00
|
|
|
AppendText(fmt_tl("* Failed to copy %s.\n", path), 2);
|
2012-01-12 23:32:09 +01:00
|
|
|
allOk = false;
|
|
|
|
}
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
if (allOk)
|
|
|
|
AppendText(_("Done. All fonts copied."), 1);
|
|
|
|
else
|
|
|
|
AppendText(_("Done. Some fonts could not be copied."), 2);
|
2012-04-08 04:28:43 +02:00
|
|
|
|
|
|
|
if (total_size > 32 * 1024 * 1024)
|
|
|
|
AppendText(_("\nOver 32 MB of fonts were copied. Some of the fonts may not be loaded by the player if they are all attached to a Matroska file."), 2);
|
2012-04-08 04:28:50 +02:00
|
|
|
|
2013-01-04 16:01:50 +01:00
|
|
|
AppendText("\n", 0);
|
2008-01-20 07:46:10 +01:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
collector->AddPendingEvent(wxThreadEvent(EVT_COLLECTION_DONE));
|
2013-01-04 16:01:50 +01:00
|
|
|
});
|
|
|
|
}
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2012-03-09 01:24:01 +01:00
|
|
|
DialogFontsCollector::DialogFontsCollector(agi::Context *c)
|
|
|
|
: wxDialog(c->parent, -1, _("Fonts Collector"))
|
2014-03-25 22:49:26 +01:00
|
|
|
, subs(c->ass.get())
|
2015-08-22 03:17:48 +02:00
|
|
|
, path(*c->path)
|
2006-01-16 22:02:54 +01:00
|
|
|
{
|
2012-04-03 22:40:24 +02:00
|
|
|
SetIcon(GETICON(font_collector_button_16));
|
2007-07-05 01:09:40 +02:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
wxString modes[] = {
|
2012-05-10 16:18:47 +02:00
|
|
|
_("Check fonts for availability")
|
|
|
|
,_("Copy fonts to folder")
|
|
|
|
,_("Copy fonts to subtitle file's folder")
|
|
|
|
,_("Copy fonts to zipped archive")
|
|
|
|
#ifndef _WIN32
|
|
|
|
,_("Symlink fonts to folder")
|
|
|
|
#endif
|
2012-01-12 23:32:09 +01:00
|
|
|
};
|
2015-11-03 05:12:32 +01:00
|
|
|
|
|
|
|
mode = static_cast<FcMode>(mid<int>(0, OPT_GET("Tool/Fonts Collector/Action")->GetInt(), countof(modes)));
|
2012-09-28 01:44:16 +02:00
|
|
|
collection_mode = new wxRadioBox(this, -1, _("Action"), wxDefaultPosition, wxDefaultSize, countof(modes), modes, 1);
|
2015-11-03 05:12:32 +01:00
|
|
|
collection_mode->SetSelection(static_cast<int>(mode));
|
2012-01-12 23:32:09 +01:00
|
|
|
|
2015-08-22 03:17:48 +02:00
|
|
|
if (c->path->Decode("?script") == "?script")
|
2012-01-12 23:32:09 +01:00
|
|
|
collection_mode->Enable(2, false);
|
|
|
|
|
|
|
|
wxStaticBoxSizer *destination_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Destination"));
|
|
|
|
|
2012-06-21 06:32:10 +02:00
|
|
|
dest_label = new wxStaticText(this, -1, " ");
|
2021-01-16 12:13:37 +01:00
|
|
|
dest_ctrl = new wxTextCtrl(this, -1, to_wx(OPT_GET("Path/Fonts Collector Destination")->GetString()));
|
2012-06-21 06:32:10 +02:00
|
|
|
dest_browse_button = new wxButton(this, -1, _("&Browse..."));
|
2012-01-12 23:32:09 +01:00
|
|
|
|
|
|
|
wxSizer *dest_browse_sizer = new wxBoxSizer(wxHORIZONTAL);
|
2012-05-15 16:07:14 +02:00
|
|
|
dest_browse_sizer->Add(dest_ctrl, wxSizerFlags(1).Border(wxRIGHT).Align(wxALIGN_CENTER_VERTICAL));
|
2012-01-12 23:32:09 +01:00
|
|
|
dest_browse_sizer->Add(dest_browse_button, wxSizerFlags());
|
|
|
|
|
|
|
|
destination_box->Add(dest_label, wxSizerFlags().Border(wxBOTTOM));
|
|
|
|
destination_box->Add(dest_browse_sizer, wxSizerFlags().Expand());
|
|
|
|
|
|
|
|
wxStaticBoxSizer *log_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Log"));
|
2014-05-30 21:39:39 +02:00
|
|
|
collection_log = new wxStyledTextCtrl(this, -1, wxDefaultPosition, wxSize(600, 300));
|
2012-01-12 23:32:09 +01:00
|
|
|
collection_log->SetWrapMode(wxSTC_WRAP_WORD);
|
|
|
|
collection_log->SetMarginWidth(1, 0);
|
|
|
|
collection_log->SetReadOnly(true);
|
|
|
|
collection_log->StyleSetForeground(1, wxColour(0, 200, 0));
|
|
|
|
collection_log->StyleSetForeground(2, wxColour(200, 0, 0));
|
|
|
|
collection_log->StyleSetForeground(3, wxColour(200, 100, 0));
|
|
|
|
log_box->Add(collection_log, wxSizerFlags().Border());
|
|
|
|
|
|
|
|
wxStdDialogButtonSizer *button_sizer = CreateStdDialogButtonSizer(wxOK | wxCANCEL | wxHELP);
|
|
|
|
start_btn = button_sizer->GetAffirmativeButton();
|
|
|
|
close_btn = button_sizer->GetCancelButton();
|
|
|
|
start_btn->SetLabel(_("&Start!"));
|
|
|
|
start_btn->SetDefault();
|
|
|
|
|
|
|
|
wxSizer *main_sizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
main_sizer->Add(collection_mode, wxSizerFlags().Expand().Border());
|
|
|
|
main_sizer->Add(destination_box, wxSizerFlags().Expand().Border(wxALL & ~wxTOP));
|
|
|
|
main_sizer->Add(log_box, wxSizerFlags().Border(wxALL & ~wxTOP));
|
|
|
|
main_sizer->Add(button_sizer, wxSizerFlags().Right().Border(wxALL & ~wxTOP));
|
|
|
|
|
|
|
|
SetSizerAndFit(main_sizer);
|
2007-06-20 07:18:47 +02:00
|
|
|
CenterOnParent();
|
2006-12-30 21:58:24 +01:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
// Update the browse button and label
|
2015-11-03 05:12:32 +01:00
|
|
|
UpdateControls();
|
Note: This was done using a script! it's far from perfect but 95% of the work has been done already formatting-wise.
Document all functions, class, struct, union, enum, macro, variable, typedefs. This isn't the actual document in itself but empty documentation using any old documentation if it was there.
This was done using exuberant ctags to get tag info, then a TCL script to parse/remove old comments and convert them into Doxygen-style.
Some notes:
* Anything labeled 'DOCME' needs to be documented, @param and @return have been left blank as it would be annoying to delete the 'DOCME' from every one of those.
* Some multiline comments may have been munged into single line comments
* Leave the /// comments above global variables with a space, if they're harder to read then we'll be less likey to use them.
* Enum comments can go after the enumeration itself '[value] /// comment'
* include/aegisub/*.h haven't been converted yet, this will be done in a later commit
* Some documentation blocks are in the wrong place, in the .h when it should be in the .cpp, or vice versa.
See http://devel.aegisub.org/wiki/Doxygen for some details on Doxygen and a 'style guide'.
Originally committed to SVN as r3312.
2009-07-30 00:59:22 +02:00
|
|
|
|
2013-12-12 03:25:13 +01:00
|
|
|
start_btn->Bind(wxEVT_BUTTON, &DialogFontsCollector::OnStart, this);
|
|
|
|
dest_browse_button->Bind(wxEVT_BUTTON, &DialogFontsCollector::OnBrowse, this);
|
|
|
|
collection_mode->Bind(wxEVT_RADIOBOX, &DialogFontsCollector::OnRadio, this);
|
|
|
|
button_sizer->GetHelpButton()->Bind(wxEVT_BUTTON, std::bind(&HelpButton::OpenPage, "Fonts Collector"));
|
2012-01-12 23:32:09 +01:00
|
|
|
Bind(EVT_ADD_TEXT, &DialogFontsCollector::OnAddText, this);
|
|
|
|
Bind(EVT_COLLECTION_DONE, &DialogFontsCollector::OnCollectionComplete, this);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
void DialogFontsCollector::OnStart(wxCommandEvent &) {
|
|
|
|
collection_log->SetReadOnly(false);
|
|
|
|
collection_log->ClearAll();
|
|
|
|
collection_log->SetReadOnly(true);
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2021-01-16 12:13:37 +01:00
|
|
|
agi::fs::path dest_path;
|
2015-11-01 05:12:24 +01:00
|
|
|
if (mode != FcMode::CheckFontsOnly) {
|
2021-01-16 12:13:37 +01:00
|
|
|
auto dest = mode == FcMode::CopyToScriptFolder ? "?script/" : from_wx(dest_ctrl->GetValue());
|
|
|
|
dest_path = path.Decode(dest);
|
2012-01-12 23:32:09 +01:00
|
|
|
|
2015-11-01 05:12:24 +01:00
|
|
|
if (mode != FcMode::CopyToZip) {
|
2021-01-16 12:13:37 +01:00
|
|
|
if (agi::fs::FileExists(dest_path))
|
2012-03-29 01:59:19 +02:00
|
|
|
wxMessageBox(_("Invalid destination."), _("Error"), wxOK | wxICON_ERROR | wxCENTER, this);
|
2013-01-04 16:01:50 +01:00
|
|
|
try {
|
2021-01-16 12:13:37 +01:00
|
|
|
agi::fs::CreateDirectory(dest_path);
|
2013-01-04 16:01:50 +01:00
|
|
|
}
|
|
|
|
catch (agi::Exception const&) {
|
2012-03-29 01:59:19 +02:00
|
|
|
wxMessageBox(_("Could not create destination folder."), _("Error"), wxOK | wxICON_ERROR | wxCENTER, this);
|
2007-06-20 09:10:41 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2021-01-16 12:13:37 +01:00
|
|
|
else if (agi::fs::DirectoryExists(dest_path) || dest_path.filename().empty()) {
|
2012-03-29 01:59:19 +02:00
|
|
|
wxMessageBox(_("Invalid path for .zip file."), _("Error"), wxOK | wxICON_ERROR | wxCENTER, this);
|
2007-06-20 07:18:47 +02:00
|
|
|
return;
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2021-01-16 12:13:37 +01:00
|
|
|
OPT_SET("Path/Fonts Collector Destination")->SetString(dest);
|
|
|
|
}
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
// Disable the UI while it runs as we don't support canceling
|
|
|
|
EnableCloseButton(false);
|
|
|
|
start_btn->Enable(false);
|
|
|
|
dest_browse_button->Enable(false);
|
|
|
|
dest_ctrl->Enable(false);
|
|
|
|
close_btn->Enable(false);
|
|
|
|
collection_mode->Enable(false);
|
|
|
|
dest_label->Enable(false);
|
2006-12-18 23:24:25 +01:00
|
|
|
|
2021-01-16 12:13:37 +01:00
|
|
|
FontsCollectorThread(subs, dest_path, mode, GetEventHandler());
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
void DialogFontsCollector::OnBrowse(wxCommandEvent &) {
|
|
|
|
wxString dest;
|
2015-11-01 05:12:24 +01:00
|
|
|
if (mode == FcMode::CopyToZip) {
|
2012-01-12 23:32:09 +01:00
|
|
|
dest = wxFileSelector(
|
|
|
|
_("Select archive file name"),
|
|
|
|
dest_ctrl->GetValue(),
|
|
|
|
wxFileName(dest_ctrl->GetValue()).GetFullName(),
|
2012-03-27 02:49:53 +02:00
|
|
|
".zip", "Zip Archives (*.zip)|*.zip",
|
2012-01-12 23:32:09 +01:00
|
|
|
wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
dest = wxDirSelector(_("Select folder to save fonts on"), dest_ctrl->GetValue(), 0);
|
|
|
|
|
|
|
|
if (!dest.empty())
|
|
|
|
dest_ctrl->SetValue(dest);
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
|
|
|
|
2015-11-01 05:12:24 +01:00
|
|
|
void DialogFontsCollector::OnRadio(wxCommandEvent &evt) {
|
|
|
|
OPT_SET("Tool/Fonts Collector/Action")->SetInt(evt.GetInt());
|
|
|
|
mode = static_cast<FcMode>(evt.GetInt());
|
2015-11-03 05:12:32 +01:00
|
|
|
UpdateControls();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DialogFontsCollector::UpdateControls() {
|
2012-01-12 23:32:09 +01:00
|
|
|
wxString dst = dest_ctrl->GetValue();
|
2006-01-16 22:02:54 +01:00
|
|
|
|
2015-11-01 05:12:24 +01:00
|
|
|
if (mode == FcMode::CheckFontsOnly || mode == FcMode::CopyToScriptFolder) {
|
2012-01-12 23:32:09 +01:00
|
|
|
dest_ctrl->Enable(false);
|
|
|
|
dest_browse_button->Enable(false);
|
|
|
|
dest_label->Enable(false);
|
|
|
|
dest_label->SetLabel(_("N/A"));
|
2008-01-20 07:46:10 +01:00
|
|
|
}
|
2008-01-14 06:54:58 +01:00
|
|
|
else {
|
2012-01-12 23:32:09 +01:00
|
|
|
dest_ctrl->Enable(true);
|
|
|
|
dest_browse_button->Enable(true);
|
|
|
|
dest_label->Enable(true);
|
2008-01-14 06:54:58 +01:00
|
|
|
|
2015-11-01 05:12:24 +01:00
|
|
|
if (mode == FcMode::CopyToFolder || mode == FcMode::SymlinkToFolder) {
|
2012-02-01 05:17:39 +01:00
|
|
|
dest_label->SetLabel(_("Choose the folder where the fonts will be collected to. It will be created if it doesn't exist."));
|
2007-06-20 09:10:41 +02:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
// Remove filename from browse box
|
|
|
|
if (dst.Right(4) == ".zip")
|
|
|
|
dest_ctrl->SetValue(wxFileName(dst).GetPath());
|
2008-01-11 05:36:29 +01:00
|
|
|
}
|
2007-06-20 08:29:20 +02:00
|
|
|
else {
|
2012-02-01 05:17:39 +01:00
|
|
|
dest_label->SetLabel(_("Enter the name of the destination zip file to collect the fonts to. If a folder is entered, a default name will be used."));
|
2007-06-20 08:29:20 +02:00
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
// Add filename to browse box
|
|
|
|
if (!dst.EndsWith(".zip")) {
|
|
|
|
wxFileName fn(dst + "//");
|
|
|
|
fn.SetFullName("fonts.zip");
|
|
|
|
dest_ctrl->SetValue(fn.GetFullPath());
|
2007-06-20 08:29:20 +02:00
|
|
|
}
|
|
|
|
}
|
2007-06-20 07:18:47 +02:00
|
|
|
}
|
2015-11-07 05:12:52 +01:00
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
// wxStaticText auto-wraps everywhere but OS X
|
|
|
|
dest_label->Wrap(dest_label->GetParent()->GetSize().GetWidth() - 20);
|
|
|
|
Layout();
|
|
|
|
#endif
|
2007-06-20 07:18:47 +02:00
|
|
|
}
|
|
|
|
|
2015-01-01 17:12:05 +01:00
|
|
|
void DialogFontsCollector::OnAddText(ValueEvent<color_str_pair> &event) {
|
|
|
|
auto const& str = event.Get();
|
2012-01-12 23:32:09 +01:00
|
|
|
collection_log->SetReadOnly(false);
|
2014-05-30 21:39:39 +02:00
|
|
|
int pos = collection_log->GetLength();
|
|
|
|
auto const& utf8 = str.second.utf8_str();
|
|
|
|
collection_log->AppendTextRaw(utf8.data(), utf8.length());
|
2012-01-12 23:32:09 +01:00
|
|
|
if (str.first) {
|
2020-11-22 19:17:19 +01:00
|
|
|
#if wxVERSION_NUMBER >= 3100
|
|
|
|
collection_log->StartStyling(pos);
|
|
|
|
#else
|
|
|
|
collection_log->StartStyling(pos, 255);
|
|
|
|
#endif
|
2014-05-30 21:39:39 +02:00
|
|
|
collection_log->SetStyling(utf8.length(), str.first);
|
2012-01-12 23:32:09 +01:00
|
|
|
}
|
2014-05-30 21:39:39 +02:00
|
|
|
collection_log->GotoPos(pos + utf8.length());
|
2012-01-12 23:32:09 +01:00
|
|
|
collection_log->SetReadOnly(true);
|
2007-06-20 07:18:47 +02:00
|
|
|
}
|
|
|
|
|
2012-01-12 23:32:09 +01:00
|
|
|
void DialogFontsCollector::OnCollectionComplete(wxThreadEvent &) {
|
2012-02-23 20:28:19 +01:00
|
|
|
EnableCloseButton(true);
|
2012-01-12 23:32:09 +01:00
|
|
|
start_btn->Enable();
|
|
|
|
close_btn->Enable();
|
|
|
|
collection_mode->Enable();
|
2015-08-22 03:17:48 +02:00
|
|
|
if (path.Decode("?script") == "?script")
|
2012-01-12 23:32:09 +01:00
|
|
|
collection_mode->Enable(2, false);
|
2007-06-20 07:18:47 +02:00
|
|
|
|
2019-09-03 17:58:20 +02:00
|
|
|
UpdateControls();
|
2006-01-16 22:02:54 +01:00
|
|
|
}
|
2014-05-22 21:07:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void ShowFontsCollectorDialog(agi::Context *c) {
|
|
|
|
c->dialog->Show<DialogFontsCollector>(c);
|
|
|
|
}
|