diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/font.cc | 51 | ||||
| -rw-r--r-- | src/lib/font.h | 24 | ||||
| -rw-r--r-- | src/lib/font_files.cc | 32 | ||||
| -rw-r--r-- | src/lib/font_files.h | 50 | ||||
| -rw-r--r-- | src/lib/player_subtitles.cc | 2 | ||||
| -rw-r--r-- | src/lib/reel_writer.cc | 10 | ||||
| -rw-r--r-- | src/lib/render_subtitles.cc | 131 | ||||
| -rw-r--r-- | src/lib/subtitle_content.cc | 4 | ||||
| -rw-r--r-- | src/lib/wscript | 1 | ||||
| -rw-r--r-- | src/wx/font_files_dialog.cc | 113 | ||||
| -rw-r--r-- | src/wx/font_files_dialog.h | 48 | ||||
| -rw-r--r-- | src/wx/fonts_dialog.cc | 132 | ||||
| -rw-r--r-- | src/wx/fonts_dialog.h | 7 | ||||
| -rw-r--r-- | src/wx/hints_dialog.cc | 8 | ||||
| -rw-r--r-- | src/wx/screen_dialog.h | 1 | ||||
| -rw-r--r-- | src/wx/wscript | 1 |
16 files changed, 468 insertions, 147 deletions
diff --git a/src/lib/font.cc b/src/lib/font.cc index d729c2696..e9df66cf7 100644 --- a/src/lib/font.cc +++ b/src/lib/font.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2014-2015 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,26 +18,67 @@ */ #include "font.h" +#include "dcpomatic_assert.h" #include <libxml++/libxml++.h> +#include <boost/foreach.hpp> + +using std::string; + +static char const * names[] = { + "Normal", + "Italic", + "Bold" +}; Font::Font (cxml::NodePtr node) : _id (node->string_child ("Id")) - , _file (node->optional_string_child ("File")) { + DCPOMATIC_ASSERT (FontFiles::VARIANTS == 3); + BOOST_FOREACH (cxml::NodePtr i, node->node_children ("File")) { + string variant = i->optional_string_attribute("Variant").get_value_or ("Normal"); + for (int j = 0; j < FontFiles::VARIANTS; ++j) { + if (variant == names[j]) { + _files.set (static_cast<FontFiles::Variant>(j), i->content()); + } + } + } } void Font::as_xml (xmlpp::Node* node) { + DCPOMATIC_ASSERT (FontFiles::VARIANTS == 3); + node->add_child("Id")->add_child_text (_id); - if (_file) { - node->add_child("File")->add_child_text (_file.get().string ()); + for (int i = 0; i < FontFiles::VARIANTS; ++i) { + if (_files.get(static_cast<FontFiles::Variant>(i))) { + xmlpp::Element* e = node->add_child ("File"); + e->set_attribute ("Variant", names[i]); + e->add_child_text (_files.get(static_cast<FontFiles::Variant>(i)).get().string ()); + } } } + +bool +operator== (Font const & a, Font const & b) +{ + if (a.id() != b.id()) { + return false; + } + + for (int i = 0; i < FontFiles::VARIANTS; ++i) { + if (a.file(static_cast<FontFiles::Variant>(i)) != b.file(static_cast<FontFiles::Variant>(i))) { + return false; + } + } + + return true; +} + bool operator!= (Font const & a, Font const & b) { - return (a.id() != b.id() || a.file() != b.file()); + return !(a == b); } diff --git a/src/lib/font.h b/src/lib/font.h index ca7650cc1..c165fea9f 100644 --- a/src/lib/font.h +++ b/src/lib/font.h @@ -20,6 +20,7 @@ #ifndef DCPOMATIC_FONT_H #define DCPOMATIC_FONT_H +#include "font_files.h" #include <libcxml/cxml.h> #include <boost/optional.hpp> #include <boost/signals2.hpp> @@ -40,12 +41,21 @@ public: return _id; } - boost::optional<boost::filesystem::path> file () const { - return _file; + boost::optional<boost::filesystem::path> file (FontFiles::Variant variant) const { + return _files.get (variant); } - void set_file (boost::filesystem::path file) { - _file = file; + void set_file (FontFiles::Variant variant, boost::filesystem::path file) { + _files.set (variant, file); + Changed (); + } + + FontFiles files () const { + return _files; + } + + void set_files (FontFiles files) { + _files = files; Changed (); } @@ -54,10 +64,10 @@ public: private: /** Font ID, used to describe it in the subtitle content */ std::string _id; - boost::optional<boost::filesystem::path> _file; + FontFiles _files; }; -bool -operator!= (Font const & a, Font const & b); +bool operator!= (Font const & a, Font const & b); +bool operator== (Font const & a, Font const & b); #endif diff --git a/src/lib/font_files.cc b/src/lib/font_files.cc new file mode 100644 index 000000000..65b67f7b3 --- /dev/null +++ b/src/lib/font_files.cc @@ -0,0 +1,32 @@ +/* + Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "font_files.h" + +bool +operator!= (FontFiles const & a, FontFiles const & b) +{ + for (int i = 0; i < FontFiles::VARIANTS; ++i) { + if (a.get(static_cast<FontFiles::Variant>(i)) != b.get(static_cast<FontFiles::Variant>(i))) { + return false; + } + } + + return true; +} diff --git a/src/lib/font_files.h b/src/lib/font_files.h new file mode 100644 index 000000000..68e7ac03f --- /dev/null +++ b/src/lib/font_files.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef DCPOMATIC_FONT_FILES_H +#define DCPOMATIC_FONT_FILES_H + +#include <boost/filesystem.hpp> +#include <boost/optional.hpp> + +class FontFiles +{ +public: + enum Variant { + NORMAL, + ITALIC, + BOLD, + VARIANTS + }; + + void set (Variant variant, boost::filesystem::path file) { + _file[variant] = file; + } + + boost::optional<boost::filesystem::path> get (Variant variant) const { + return _file[variant]; + } + +private: + boost::optional<boost::filesystem::path> _file[VARIANTS]; +}; + +bool operator!= (FontFiles const & a, FontFiles const & b); + +#endif diff --git a/src/lib/player_subtitles.cc b/src/lib/player_subtitles.cc index da5714349..8838b2f64 100644 --- a/src/lib/player_subtitles.cc +++ b/src/lib/player_subtitles.cc @@ -30,7 +30,7 @@ PlayerSubtitles::add_fonts (list<shared_ptr<Font> > fonts_) BOOST_FOREACH (shared_ptr<Font> i, fonts_) { bool got = false; BOOST_FOREACH (shared_ptr<Font> j, fonts) { - if (i->file() == j->file()) { + if (*i == *j) { got = true; } } diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc index 743f73dff..803c2a8ed 100644 --- a/src/lib/reel_writer.cc +++ b/src/lib/reel_writer.cc @@ -363,17 +363,19 @@ ReelWriter::create_reel (list<ReferencedReelAsset> const & refs, list<shared_ptr } if (_subtitle_asset) { - boost::filesystem::path liberation; + + boost::filesystem::path liberation_normal; try { - liberation = shared_path () / "LiberationSans-Regular.ttf"; + liberation_normal = shared_path () / "LiberationSans-Regular.ttf"; } catch (boost::filesystem::filesystem_error& e) { /* Hack: try the debian/ubuntu location if getting the shared path failed */ - liberation = "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf"; + liberation_normal = "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf"; } + /* Add all the fonts to the subtitle content */ BOOST_FOREACH (shared_ptr<Font> j, fonts) { - _subtitle_asset->add_font (j->id(), j->file().get_value_or (liberation)); + _subtitle_asset->add_font (j->id(), j->file(FontFiles::NORMAL).get_value_or(liberation_normal)); } if (dynamic_pointer_cast<dcp::InteropSubtitleAsset> (_subtitle_asset)) { diff --git a/src/lib/render_subtitles.cc b/src/lib/render_subtitles.cc index f507238fb..9b5f585e5 100644 --- a/src/lib/render_subtitles.cc +++ b/src/lib/render_subtitles.cc @@ -22,6 +22,7 @@ #include "image.h" #include "cross.h" #include "font.h" +#include "dcpomatic_assert.h" #include <cairomm/cairomm.h> #include <pangomm.h> #include <boost/foreach.hpp> @@ -39,23 +40,30 @@ using boost::shared_ptr; using boost::optional; static FcConfig* fc_config = 0; -static list<pair<boost::filesystem::path, string> > fc_config_fonts; +static list<pair<FontFiles, string> > fc_config_fonts; +/** @param subtitles A list of subtitles that are all on the same line */ static PositionImage -render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > fonts, dcp::Size target) +render_line (list<dcp::SubtitleString> subtitles, list<shared_ptr<Font> > fonts, dcp::Size target) { + /* XXX: this method can only handle italic / bold changes mid-line, + nothing else yet. + */ + + DCPOMATIC_ASSERT (!subtitles.empty ()); + /* Calculate x and y scale factors. These are only used to stretch the font away from its normal aspect ratio. */ float xscale = 1; float yscale = 1; - if (fabs (subtitle.aspect_adjust() - 1.0) > dcp::ASPECT_ADJUST_EPSILON) { - if (subtitle.aspect_adjust() < 1) { - xscale = max (0.25f, subtitle.aspect_adjust ()); + if (fabs (subtitles.front().aspect_adjust() - 1.0) > dcp::ASPECT_ADJUST_EPSILON) { + if (subtitles.front().aspect_adjust() < 1) { + xscale = max (0.25f, subtitles.front().aspect_adjust ()); yscale = 1; } else { xscale = 1; - yscale = 1 / min (4.0f, subtitle.aspect_adjust ()); + yscale = 1 / min (4.0f, subtitles.front().aspect_adjust ()); } } @@ -64,7 +72,7 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f */ /* Basic guess on height... */ - int height = subtitle.size() * target.height / (11 * 72); + int height = subtitles.front().size() * target.height / (11 * 72); /* ...scaled... */ height *= yscale; /* ...and add a bit more for luck */ @@ -87,22 +95,36 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f fc_config = FcConfigCreate (); } - boost::filesystem::path font_file; + FontFiles font_files; + try { - font_file = shared_path () / "LiberationSans-Regular.ttf"; + font_files.set (FontFiles::NORMAL, shared_path () / "LiberationSans-Regular.ttf"); + font_files.set (FontFiles::ITALIC, shared_path () / "LiberationSans-Italic.ttf"); + font_files.set (FontFiles::BOLD, shared_path () / "LiberationSans-Bold.ttf"); } catch (boost::filesystem::filesystem_error& e) { - /* Hack: try the debian/ubuntu location if getting the shared path failed */ - font_file = "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf"; + + } + + /* Hack: try the debian/ubuntu locations if getting the shared path failed */ + + if (!font_files.get(FontFiles::NORMAL) || !boost::filesystem::exists(font_files.get(FontFiles::NORMAL).get())) { + font_files.set (FontFiles::NORMAL, "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf"); + } + if (!font_files.get(FontFiles::ITALIC) || !boost::filesystem::exists(font_files.get(FontFiles::ITALIC).get())) { + font_files.set (FontFiles::ITALIC, "/usr/share/fonts/truetype/liberation/LiberationSans-Italic.ttf"); + } + if (!font_files.get(FontFiles::BOLD) || !boost::filesystem::exists(font_files.get(FontFiles::BOLD).get())) { + font_files.set (FontFiles::BOLD, "/usr/share/fonts/truetype/liberation/LiberationSans-Bold.ttf"); } BOOST_FOREACH (shared_ptr<Font> i, fonts) { - if (i->id() == subtitle.font() && i->file ()) { - font_file = i->file().get (); + if (i->id() == subtitles.front().font() && i->file(FontFiles::NORMAL)) { + font_files = i->files (); } } - list<pair<boost::filesystem::path, string> >::const_iterator existing = fc_config_fonts.begin (); - while (existing != fc_config_fonts.end() && existing->first != font_file) { + list<pair<FontFiles, string> >::const_iterator existing = fc_config_fonts.begin (); + while (existing != fc_config_fonts.end() && existing->first != font_files) { ++existing; } @@ -111,9 +133,16 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f font_name = existing->second; } else { /* Make this font available to DCP-o-matic */ - FcConfigAppFontAddFile (fc_config, reinterpret_cast<FcChar8 const *> (font_file.string().c_str ())); + for (int i = 0; i < FontFiles::VARIANTS; ++i) { + if (font_files.get(static_cast<FontFiles::Variant>(i))) { + FcConfigAppFontAddFile ( + fc_config, + reinterpret_cast<FcChar8 const *> (font_files.get(static_cast<FontFiles::Variant>(i)).get().string().c_str()) + ); + } + } - FcPattern* pattern = FcPatternBuild (0, FC_FILE, FcTypeString, font_file.string().c_str(), static_cast<char *> (0)); + FcPattern* pattern = FcPatternBuild (0, FC_FILE, FcTypeString, font_files.get(FontFiles::NORMAL).get().string().c_str(), static_cast<char *> (0)); FcObjectSet* object_set = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_LANG, FC_FILE, static_cast<char *> (0)); FcFontSet* font_set = FcFontList (fc_config, pattern, object_set); if (font_set) { @@ -137,7 +166,7 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f FcObjectSetDestroy (object_set); FcPatternDestroy (pattern); - fc_config_fonts.push_back (make_pair (font_file, font_name)); + fc_config_fonts.push_back (make_pair (font_files, font_name)); } FcConfigSetCurrent (fc_config); @@ -151,12 +180,29 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f /* Render the subtitle at the top left-hand corner of image */ Pango::FontDescription font (font_name); - font.set_absolute_size (subtitle.size_in_pixels (target.height) * PANGO_SCALE); - if (subtitle.italic ()) { - font.set_style (Pango::STYLE_ITALIC); - } + font.set_absolute_size (subtitles.front().size_in_pixels (target.height) * PANGO_SCALE); layout->set_font_description (font); - layout->set_text (subtitle.text ()); + + string marked_up; + bool italic = false; + BOOST_FOREACH (dcp::SubtitleString const & i, subtitles) { + if (i.italic() != italic) { + if (i.italic()) { + marked_up += "<i>"; + } else { + marked_up += "</i>"; + } + italic = i.italic (); + } + + marked_up += i.text (); + } + + if (italic) { + marked_up += "</i>"; + } + + layout->set_markup (marked_up); /* Compute fade factor */ /* XXX */ @@ -166,9 +212,9 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f context->scale (xscale, yscale); - if (subtitle.effect() == dcp::SHADOW) { + if (subtitles.front().effect() == dcp::SHADOW) { /* Drop-shadow effect */ - dcp::Colour const ec = subtitle.effect_colour (); + dcp::Colour const ec = subtitles.front().effect_colour (); context->set_source_rgba (float(ec.r) / 255, float(ec.g) / 255, float(ec.b) / 255, fade_factor); context->move_to (4, 4); layout->add_to_cairo_context (context); @@ -177,15 +223,15 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f /* The actual subtitle */ - dcp::Colour const c = subtitle.colour (); + dcp::Colour const c = subtitles.front().colour (); context->set_source_rgba (float(c.r) / 255, float(c.g) / 255, float(c.b) / 255, fade_factor); context->move_to (0, 0); layout->add_to_cairo_context (context); context->fill (); - if (subtitle.effect() == dcp::BORDER) { + if (subtitles.front().effect() == dcp::BORDER) { /* Border effect */ - dcp::Colour ec = subtitle.effect_colour (); + dcp::Colour ec = subtitles.front().effect_colour (); context->set_source_rgba (float(ec.r) / 255, float(ec.g) / 255, float(ec.b) / 255, fade_factor); context->move_to (0, 0); layout->add_to_cairo_context (context); @@ -197,34 +243,34 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f layout->get_size (layout_width, layout_height); int x = 0; - switch (subtitle.h_align ()) { + switch (subtitles.front().h_align ()) { case dcp::HALIGN_LEFT: /* h_position is distance between left of frame and left of subtitle */ - x = subtitle.h_position() * target.width; + x = subtitles.front().h_position() * target.width; break; case dcp::HALIGN_CENTER: /* h_position is distance between centre of frame and centre of subtitle */ - x = (0.5 + subtitle.h_position()) * target.width - layout_width / (PANGO_SCALE * 2); + x = (0.5 + subtitles.front().h_position()) * target.width - layout_width / (PANGO_SCALE * 2); break; case dcp::HALIGN_RIGHT: /* h_position is distance between right of frame and right of subtitle */ - x = (1.0 - subtitle.h_position()) * target.width - layout_width / PANGO_SCALE; + x = (1.0 - subtitles.front().h_position()) * target.width - layout_width / PANGO_SCALE; break; } int y = 0; - switch (subtitle.v_align ()) { + switch (subtitles.front().v_align ()) { case dcp::VALIGN_TOP: /* v_position is distance between top of frame and top of subtitle */ - y = subtitle.v_position() * target.height; + y = subtitles.front().v_position() * target.height; break; case dcp::VALIGN_CENTER: /* v_position is distance between centre of frame and centre of subtitle */ - y = (0.5 + subtitle.v_position()) * target.height - layout_height / (PANGO_SCALE * 2); + y = (0.5 + subtitles.front().v_position()) * target.height - layout_height / (PANGO_SCALE * 2); break; case dcp::VALIGN_BOTTOM: /* v_position is distance between bottom of frame and bottom of subtitle */ - y = (1.0 - subtitle.v_position()) * target.height - layout_height / PANGO_SCALE; + y = (1.0 - subtitles.front().v_position()) * target.height - layout_height / PANGO_SCALE; break; } @@ -234,9 +280,20 @@ render_subtitle (dcp::SubtitleString const & subtitle, list<shared_ptr<Font> > f list<PositionImage> render_subtitles (list<dcp::SubtitleString> subtitles, list<shared_ptr<Font> > fonts, dcp::Size target) { + list<dcp::SubtitleString> pending; list<PositionImage> images; + BOOST_FOREACH (dcp::SubtitleString const & i, subtitles) { - images.push_back (render_subtitle (i, fonts, target)); + if (!pending.empty() && fabs (i.v_position() - pending.back().v_position()) > 1e-4) { + images.push_back (render_line (pending, fonts, target)); + pending.clear (); + } + pending.push_back (i); } + + if (!pending.empty ()) { + images.push_back (render_line (pending, fonts, target)); + } + return images; } diff --git a/src/lib/subtitle_content.cc b/src/lib/subtitle_content.cc index 2f4c88975..d779a7642 100644 --- a/src/lib/subtitle_content.cc +++ b/src/lib/subtitle_content.cc @@ -275,7 +275,9 @@ SubtitleContent::identifier () const types of subtitle content involve fonts. */ BOOST_FOREACH (shared_ptr<Font> f, _fonts) { - s << f->file().get_value_or ("Default"); + for (int i = 0; i < FontFiles::VARIANTS; ++i) { + s << "_" << f->file(static_cast<FontFiles::Variant>(i)).get_value_or ("Default"); + } } /* The language is for metadata only, and doesn't affect diff --git a/src/lib/wscript b/src/lib/wscript index c6c73662b..263d222c2 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -72,6 +72,7 @@ sources = """ film.cc filter.cc font.cc + font_files.cc frame_rate_change.cc internet.cc image.cc diff --git a/src/wx/font_files_dialog.cc b/src/wx/font_files_dialog.cc new file mode 100644 index 000000000..080a8ebc6 --- /dev/null +++ b/src/wx/font_files_dialog.cc @@ -0,0 +1,113 @@ +/* + Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "font_files_dialog.h" +#include "system_font_dialog.h" + +using boost::bind; + +FontFilesDialog::FontFilesDialog (wxWindow* parent, FontFiles files) +#ifdef DCPOMATIC_WINDOWS + : TableDialog (parent, _("Fonts"), 4, 1, true) +#else + : TableDialog (parent, _("Fonts"), 3, 1, true) +#endif + , _files (files) +{ + wxString labels[] = { + _("Normal font"), + _("Italic font"), + _("Bold font") + }; + + DCPOMATIC_ASSERT (FontFiles::VARIANTS == 3); + + for (int i = 0; i < FontFiles::VARIANTS; ++i) { + add (labels[i], true); + _name[i] = new wxStaticText ( + this, wxID_ANY, + std_to_wx(_files.get(static_cast<FontFiles::Variant>(i)).get_value_or("").string()), + wxDefaultPosition, + wxSize (200, -1) + ); + _table->Add (_name[i], 1, wxEXPAND | wxALIGN_CENTER_VERTICAL | wxALL, 6); + add (_set_file[i] = new wxButton (this, wxID_ANY, _("Set from file..."))); + _set_file[i]->Bind (wxEVT_COMMAND_BUTTON_CLICKED, bind (&FontFilesDialog::set_from_file_clicked, this, static_cast<FontFiles::Variant>(i))); +#ifdef DCPOMATIC_WINDOWS + add (_set_system[i] = new wxButton (this, wxID_ANY, _("Set from system font..."))); + _set_system[i]->Bind (wxEVT_COMMAND_BUTTON_CLICKED, bind (&FontFilesDialog::set_from_system_clicked, this, static_cast<FontFiles::Variant>(i))); +#endif + } + + layout (); +} + +void +FontFilesDialog::set_from_file_clicked (FontFiles::Variant variant) +{ + /* The wxFD_CHANGE_DIR here prevents a `could not set working directory' error 123 on Windows when using + non-Latin filenames or paths. + */ + wxString default_dir = ""; +#ifdef DCPOMATIC_LINUX + if (boost::filesystem::exists ("/usr/share/fonts/truetype")) { + default_dir = "/usr/share/fonts/truetype"; + } else { + default_dir = "/usr/share/fonts"; + } +#endif +#ifdef DCPOMATIC_OSX + default_dir = "/System/Library/Fonts"; +#endif + + wxFileDialog* d = new wxFileDialog (this, _("Choose a font file"), default_dir, wxT (""), wxT ("*.ttf"), wxFD_CHANGE_DIR); + int const r = d->ShowModal (); + + if (r != wxID_OK) { + d->Destroy (); + return; + } + + set (variant, wx_to_std (d->GetPath ())); + d->Destroy (); +} + +#ifdef DCPOMATIC_WINDOWS +void +FontFilesDialog::set_from_system_clicked (FontFiles::Variant variant) +{ + SystemFontDialog* d = new SystemFontDialog (this); + int const r = d->ShowModal (); + + if (r != wxID_OK) { + d->Destroy (); + return; + } + + set (variant, d->get_font().get()); + d->Destroy (); +} +#endif + +void +FontFilesDialog::set (FontFiles::Variant variant, boost::filesystem::path path) +{ + _files.set (variant, path); + _name[variant]->SetLabel (std_to_wx (path.leaf().string())); +} diff --git a/src/wx/font_files_dialog.h b/src/wx/font_files_dialog.h new file mode 100644 index 000000000..dd53cd5ab --- /dev/null +++ b/src/wx/font_files_dialog.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2015 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "table_dialog.h" +#include "wx_util.h" +#include "lib/font_files.h" + +class FontFilesDialog : public TableDialog +{ +public: + FontFilesDialog (wxWindow* parent, FontFiles files); + + FontFiles get () const { + return _files; + } + +private: + void set_from_file_clicked (FontFiles::Variant variant); +#ifdef DCPOMATIC_WINDOWS + void set_from_system_clicked (FontFiles::Variant variant); +#endif + void set (FontFiles::Variant variant, boost::filesystem::path path); + + FontFiles _files; + + wxStaticText* _name[FontFiles::VARIANTS]; + wxButton* _set_file[FontFiles::VARIANTS]; + +#ifdef DCPOMATIC_WINDOWS + wxButton* _set_system[FontFiles::VARIANTS]; +#endif +}; diff --git a/src/wx/fonts_dialog.cc b/src/wx/fonts_dialog.cc index ff5b107c9..b79580d7c 100644 --- a/src/wx/fonts_dialog.cc +++ b/src/wx/fonts_dialog.cc @@ -20,6 +20,7 @@ #include "fonts_dialog.h" #include "wx_util.h" #include "system_font_dialog.h" +#include "font_files_dialog.h" #include "lib/font.h" #include "lib/subtitle_content.h" #include <wx/wx.h> @@ -34,9 +35,8 @@ using boost::shared_ptr; FontsDialog::FontsDialog (wxWindow* parent, shared_ptr<SubtitleContent> content) : wxDialog (parent, wxID_ANY, _("Fonts")) , _content (content) - , _set_from_system (0) { - _fonts = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (400, 200), wxLC_REPORT | wxLC_SINGLE_SEL); + _fonts = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (550, 200), wxLC_REPORT | wxLC_SINGLE_SEL); { wxListItem ip; @@ -49,25 +49,33 @@ FontsDialog::FontsDialog (wxWindow* parent, shared_ptr<SubtitleContent> content) { wxListItem ip; ip.SetId (1); - ip.SetText (_("Font file")); - ip.SetWidth (300); + ip.SetText (_("Normal file")); + ip.SetWidth (150); _fonts->InsertColumn (1, ip); } - wxBoxSizer* sizer = new wxBoxSizer (wxHORIZONTAL); - sizer->Add (_fonts, 1, wxEXPAND); + { + wxListItem ip; + ip.SetId (2); + ip.SetText (_("Italic file")); + ip.SetWidth (150); + _fonts->InsertColumn (2, ip); + } { - wxSizer* s = new wxBoxSizer (wxVERTICAL); - _set_from_file = new wxButton (this, wxID_ANY, _("Set from .ttf file...")); - s->Add (_set_from_file, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); -#ifdef DCPOMATIC_WINDOWS - _set_from_system = new wxButton (this, wxID_ANY, _("Set from system font...")); - s->Add (_set_from_system, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); -#endif - sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP); + wxListItem ip; + ip.SetId (3); + ip.SetText (_("Bold file")); + ip.SetWidth (150); + _fonts->InsertColumn (3, ip); } + wxBoxSizer* sizer = new wxBoxSizer (wxHORIZONTAL); + sizer->Add (_fonts, 1, wxEXPAND | wxLEFT | wxRIGHT, DCPOMATIC_SIZER_X_GAP); + + _edit = new wxButton (this, wxID_ANY, _("Edit...")); + sizer->Add (_edit, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP); + wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL); overall_sizer->Add (sizer, 1, wxEXPAND | wxALL, DCPOMATIC_SIZER_X_GAP); @@ -78,10 +86,7 @@ FontsDialog::FontsDialog (wxWindow* parent, shared_ptr<SubtitleContent> content) SetSizerAndFit (overall_sizer); - _set_from_file->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FontsDialog::set_from_file_clicked, this)); - if (_set_from_system) { - _set_from_system->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FontsDialog::set_from_system_clicked, this)); - } + _edit->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&FontsDialog::edit_clicked, this)); _fonts->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&FontsDialog::selection_changed, this)); _fonts->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&FontsDialog::selection_changed, this)); @@ -97,15 +102,14 @@ FontsDialog::setup () } _fonts->DeleteAllItems (); - list<shared_ptr<Font> > fonts = content->fonts (); size_t n = 0; - for (list<shared_ptr<Font> >::const_iterator i = fonts.begin(); i != fonts.end(); ++i) { + BOOST_FOREACH (shared_ptr<Font> i, content->fonts ()) { wxListItem item; item.SetId (n); _fonts->InsertItem (item); - _fonts->SetItem (n, 0, std_to_wx ((*i)->id ())); - if ((*i)->file ()) { - _fonts->SetItem (n, 1, (*i)->file().get().leaf().string ()); + _fonts->SetItem (n, 0, std_to_wx (i->id ())); + if (i->file(FontFiles::NORMAL)) { + _fonts->SetItem (n, 1, i->file(FontFiles::NORMAL).get().leaf().string ()); } ++n; } @@ -114,86 +118,44 @@ FontsDialog::setup () } void -FontsDialog::set_from_file_clicked () +FontsDialog::selection_changed () { - /* The wxFD_CHANGE_DIR here prevents a `could not set working directory' error 123 on Windows when using - non-Latin filenames or paths. - */ - wxString default_dir = ""; -#ifdef DCPOMATIC_LINUX - if (boost::filesystem::exists ("/usr/share/fonts/truetype")) { - default_dir = "/usr/share/fonts/truetype"; - } else { - default_dir = "/usr/share/fonts"; - } -#endif -#ifdef DCPOMATIC_OSX - default_dir = "/System/Library/Fonts"; -#endif - - wxFileDialog* d = new wxFileDialog (this, _("Choose a font file"), default_dir, wxT (""), wxT ("*.ttf"), wxFD_CHANGE_DIR); - int const r = d->ShowModal (); - - if (r != wxID_OK) { - d->Destroy (); - return; - } - - set_selected_font_file (wx_to_std (d->GetPath ())); - d->Destroy (); + setup_sensitivity (); } void -FontsDialog::set_from_system_clicked () +FontsDialog::setup_sensitivity () { - SystemFontDialog* d = new SystemFontDialog (this); - int const r = d->ShowModal (); - - if (r != wxID_OK) { - d->Destroy (); - return; - } - - set_selected_font_file (d->get_font().get ()); - d->Destroy (); + int const item = _fonts->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + _edit->Enable (item != -1); } void -FontsDialog::set_selected_font_file (boost::filesystem::path file) +FontsDialog::edit_clicked () { shared_ptr<SubtitleContent> content = _content.lock (); if (!content) { return; } - int item = _fonts->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - if (item == -1) { - return; - } - - string id = wx_to_std (_fonts->GetItemText (item, 0)); - - BOOST_FOREACH (shared_ptr<Font> i, content->fonts ()) { + int const item = _fonts->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); + string const id = wx_to_std (_fonts->GetItemText (item, 0)); + shared_ptr<Font> font; + BOOST_FOREACH (shared_ptr<Font> i, content->fonts()) { if (i->id() == id) { - i->set_file (file); + font = i; } } - setup (); -} - -void -FontsDialog::selection_changed () -{ - setup_sensitivity (); -} + if (!font) { + return; + } -void -FontsDialog::setup_sensitivity () -{ - int const item = _fonts->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED); - _set_from_file->Enable (item != -1); - if (_set_from_system) { - _set_from_system->Enable (item != -1); + FontFilesDialog* d = new FontFilesDialog (this, font->files ()); + if (d->ShowModal () == wxID_OK) { + font->set_files (d->get ()); } + d->Destroy (); + + setup (); } diff --git a/src/wx/fonts_dialog.h b/src/wx/fonts_dialog.h index 26c2a5eaa..e04dc9937 100644 --- a/src/wx/fonts_dialog.h +++ b/src/wx/fonts_dialog.h @@ -32,14 +32,11 @@ public: private: void setup (); - void set_from_file_clicked (); - void set_from_system_clicked (); void setup_sensitivity (); void selection_changed (); - void set_selected_font_file (boost::filesystem::path file); + void edit_clicked (); boost::weak_ptr<SubtitleContent> _content; wxListCtrl* _fonts; - wxButton* _set_from_file; - wxButton* _set_from_system; + wxButton* _edit; }; diff --git a/src/wx/hints_dialog.cc b/src/wx/hints_dialog.cc index e15263670..a63c6be62 100644 --- a/src/wx/hints_dialog.cc +++ b/src/wx/hints_dialog.cc @@ -28,6 +28,7 @@ #include <boost/foreach.hpp> using boost::shared_ptr; +using boost::optional; using boost::dynamic_pointer_cast; HintsDialog::HintsDialog (wxWindow* parent, boost::weak_ptr<Film> film) @@ -79,8 +80,11 @@ HintsDialog::film_changed () shared_ptr<SubtitleContent> s = dynamic_pointer_cast<SubtitleContent> (i); if (s) { BOOST_FOREACH (shared_ptr<Font> j, s->fonts ()) { - if (j->file() && boost::filesystem::file_size (j->file().get ()) >= (640 * 1024)) { - big_font_files = true; + for (int i = 0; i < FontFiles::VARIANTS; ++i) { + optional<boost::filesystem::path> const p = j->file (static_cast<FontFiles::Variant> (i)); + if (p && boost::filesystem::file_size (p.get()) >= (640 * 1024)) { + big_font_files = true; + } } } } diff --git a/src/wx/screen_dialog.h b/src/wx/screen_dialog.h index c88b3bb31..66f3f422f 100644 --- a/src/wx/screen_dialog.h +++ b/src/wx/screen_dialog.h @@ -21,6 +21,7 @@ #include <dcp/certificate.h> #include <wx/wx.h> #include <boost/shared_ptr.hpp> +#include <boost/optional.hpp> class Progress; diff --git a/src/wx/wscript b/src/wx/wscript index 346d292c6..d2bf33cd3 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -51,6 +51,7 @@ sources = """ filter_dialog.cc filter_editor.cc fonts_dialog.cc + font_files_dialog.cc gain_calculator_dialog.cc hints_dialog.cc job_view.cc |
