diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-11-02 22:47:57 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-11-02 22:47:57 +0000 |
| commit | 9bf2cf3509380663e6943f6b0d22dbec6002c332 (patch) | |
| tree | 86999381629818072353ffb15d78f5815efabf69 /src | |
| parent | 8a673bcf0cd26268899face63723c0f201fabcce (diff) | |
Fix incorrect preview of italic subtitles (#728).
This requires fonts to be configured with their italic versions so
that the italic font can be given to FontConfig and hence used to
render text. Bold font configuration is also added here although
bold subtitles aren't yet supported.
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 |
