+2015-11-02 Carl Hetherington <cth@carlh.net>
+
+ * Fix incorrect preview rendering of italic subtitles (#728).
+
2015-10-30 c.hetherington <cth@carlh.net>
* Updated ru_RU translation from Igor Voytovich.
/*
- 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
*/
#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);
}
#ifndef DCPOMATIC_FONT_H
#define DCPOMATIC_FONT_H
+#include "font_files.h"
#include <libcxml/cxml.h>
#include <boost/optional.hpp>
#include <boost/signals2.hpp>
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 ();
}
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
--- /dev/null
+/*
+ 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;
+}
--- /dev/null
+/*
+ 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
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;
}
}
}
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)) {
#include "image.h"
#include "cross.h"
#include "font.h"
+#include "dcpomatic_assert.h"
#include <cairomm/cairomm.h>
#include <pangomm.h>
#include <boost/foreach.hpp>
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 ());
}
}
*/
/* 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 */
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;
}
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) {
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);
/* 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 */
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);
/* 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);
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;
}
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;
}
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
film.cc
filter.cc
font.cc
+ font_files.cc
frame_rate_change.cc
internet.cc
image.cc
--- /dev/null
+/*
+ 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()));
+}
--- /dev/null
+/*
+ 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
+};
#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>
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;
{
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);
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));
}
_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;
}
}
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 ();
}
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;
};
#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)
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;
+ }
}
}
}
#include <dcp/certificate.h>
#include <wx/wx.h>
#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
class Progress;
filter_dialog.cc
filter_editor.cc
fonts_dialog.cc
+ font_files_dialog.cc
gain_calculator_dialog.cc
hints_dialog.cc
job_view.cc
content->set_use_subtitles (true);
content->set_burn_subtitles (false);
/* Use test/data/subrip2.srt as if it were a font file */
- content->fonts().front()->set_file ("test/data/subrip2.srt");
+ content->fonts().front()->set_file (FontFiles::NORMAL, "test/data/subrip2.srt");
film->make_dcp ();
wait_for_jobs ();