diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-06-09 11:13:02 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-06-09 11:13:02 +0100 |
| commit | 5c1b079a28941781c9cfa46d57e0c20b55681b32 (patch) | |
| tree | 35c0d2aac409ca1b52699e974f299a64aa5ffc1f /src | |
| parent | 6425742f95a4c2e539061b29016a4a5bd10ac9ae (diff) | |
Basically-working interop subtitle font handling.
Diffstat (limited to 'src')
| -rw-r--r-- | src/asset.cc | 8 | ||||
| -rw-r--r-- | src/dcp.cc | 18 | ||||
| -rw-r--r-- | src/font.h | 2 | ||||
| -rw-r--r-- | src/interop_subtitle_asset.cc | 50 | ||||
| -rw-r--r-- | src/interop_subtitle_asset.h | 4 | ||||
| -rw-r--r-- | src/reel.cc | 9 | ||||
| -rw-r--r-- | src/smpte_subtitle_asset.cc | 5 | ||||
| -rw-r--r-- | src/smpte_subtitle_asset.h | 1 | ||||
| -rw-r--r-- | src/subtitle_asset.cc | 23 | ||||
| -rw-r--r-- | src/subtitle_asset.h | 33 |
10 files changed, 141 insertions, 12 deletions
diff --git a/src/asset.cc b/src/asset.cc index 24fc5919..5760c905 100644 --- a/src/asset.cc +++ b/src/asset.cc @@ -71,10 +71,16 @@ Asset::write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const asset->add_child("Id")->add_child_text ("urn:uuid:" + _id); xmlpp::Node* chunk_list = asset->add_child ("ChunkList"); xmlpp::Node* chunk = chunk_list->add_child ("Chunk"); - optional<boost::filesystem::path> path = relative_to_root (root, _file); + + optional<boost::filesystem::path> path = relative_to_root ( + boost::filesystem::canonical (root), + boost::filesystem::canonical (_file) + ); + if (!path) { throw MiscError (String::compose ("Asset %1 is not within the directory %2", _file, root)); } + chunk->add_child("Path")->add_child_text (path.get().string ()); chunk->add_child("VolumeIndex")->add_child_text ("1"); chunk->add_child("Offset")->add_child_text ("0"); @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-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 @@ -29,6 +29,7 @@ #include "smpte_subtitle_asset.h" #include "mono_picture_asset.h" #include "stereo_picture_asset.h" +#include "reel_subtitle_asset.h" #include "util.h" #include "metadata.h" #include "exceptions.h" @@ -40,6 +41,7 @@ #include "decrypted_kdm_key.h" #include "dcp_assert.h" #include "reel_asset.h" +#include "font.h" #include <xmlsec/xmldsig.h> #include <xmlsec/app.h> #include <libxml++/libxml++.h> @@ -55,8 +57,10 @@ using std::ostream; using std::make_pair; using std::map; using std::cout; +using std::cerr; using std::exception; using boost::shared_ptr; +using boost::dynamic_pointer_cast; using boost::algorithm::starts_with; using namespace dcp; @@ -117,7 +121,7 @@ DCP::read (bool keep_going, ReadErrors* errors) */ /* Make a list of non-CPL assets so that we can resolve the references - from the CPL. + from the CPLs. */ list<shared_ptr<Asset> > other_assets; @@ -171,6 +175,8 @@ DCP::read (bool keep_going, ReadErrors* errors) default: throw DCPReadError ("Unknown MXF essence type"); } + } else if (boost::filesystem::extension (path) == ".ttf") { + other_assets.push_back (shared_ptr<Font> (new Font (path))); } } @@ -423,7 +429,13 @@ DCP::assets () const BOOST_FOREACH (shared_ptr<CPL> i, cpls ()) { assets.push_back (i); BOOST_FOREACH (shared_ptr<const ReelAsset> j, i->reel_assets ()) { - assets.push_back (j->asset_ref().object ()); + shared_ptr<Asset> o = j->asset_ref().object (); + assets.push_back (o); + /* More Interop special-casing */ + shared_ptr<InteropSubtitleAsset> sub = dynamic_pointer_cast<InteropSubtitleAsset> (o); + if (sub) { + sub->add_font_assets (assets); + } } } @@ -26,7 +26,7 @@ namespace dcp { /** @class Font - * @brief A (truetype) font asset for subtitles in a DCP. + * @brief A (truetype) font asset for subtitles in an Interop DCP. */ class Font : public Asset { diff --git a/src/interop_subtitle_asset.cc b/src/interop_subtitle_asset.cc index 231dda16..9565b12d 100644 --- a/src/interop_subtitle_asset.cc +++ b/src/interop_subtitle_asset.cc @@ -23,6 +23,8 @@ #include "raw_convert.h" #include "font_node.h" #include "util.h" +#include "font.h" +#include "dcp_assert.h" #include <libxml++/libxml++.h> #include <boost/foreach.hpp> #include <cmath> @@ -31,6 +33,8 @@ using std::list; using std::string; using std::cout; +using std::cerr; +using std::map; using boost::shared_ptr; using boost::optional; using boost::dynamic_pointer_cast; @@ -85,9 +89,10 @@ InteropSubtitleAsset::xml_as_string () const } void -InteropSubtitleAsset::add_font (string id, string uri) +InteropSubtitleAsset::add_font (string id, boost::filesystem::path file) { - _load_font_nodes.push_back (shared_ptr<InteropLoadFontNode> (new InteropLoadFontNode (id, uri))); + add_font_data (id, file); + _load_font_nodes.push_back (shared_ptr<InteropLoadFontNode> (new InteropLoadFontNode (id, file.leaf().string ()))); } bool @@ -136,7 +141,7 @@ InteropSubtitleAsset::load_font_nodes () const return lf; } -/** Write this content to an XML file */ +/** Write this content to an XML file with its fonts alongside */ void InteropSubtitleAsset::write (boost::filesystem::path p) const { @@ -150,4 +155,43 @@ InteropSubtitleAsset::write (boost::filesystem::path p) const fclose (f); _file = p; + + BOOST_FOREACH (shared_ptr<InteropLoadFontNode> i, _load_font_nodes) { + boost::filesystem::path file = p.parent_path() / i->uri; + FILE* f = fopen_boost (file, "w"); + if (!f) { + throw FileError ("could not open font file for writing", file, errno); + } + map<string, FontData>::const_iterator j = _fonts.find (i->id); + if (j != _fonts.end ()) { + fwrite (j->second.data.get(), 1, j->second.size, f); + j->second.file = file; + } + fclose (f); + } +} + +void +InteropSubtitleAsset::resolve_fonts (list<shared_ptr<Object> > objects) +{ + BOOST_FOREACH (shared_ptr<Object> i, objects) { + shared_ptr<Font> font = dynamic_pointer_cast<Font> (i); + if (!font) { + continue; + } + + BOOST_FOREACH (shared_ptr<InteropLoadFontNode> j, _load_font_nodes) { + if (j->uri == font->file().leaf().string ()) { + add_font_data (j->id, font->file ()); + } + } + } +} + +void +InteropSubtitleAsset::add_font_assets (list<shared_ptr<Asset> >& assets) +{ + for (map<string, FontData>::const_iterator i = _fonts.begin(); i != _fonts.end(); ++i) { + assets.push_back (shared_ptr<Font> (new Font (i->second.file))); + } } diff --git a/src/interop_subtitle_asset.h b/src/interop_subtitle_asset.h index 378bacc7..4d2c2893 100644 --- a/src/interop_subtitle_asset.h +++ b/src/interop_subtitle_asset.h @@ -47,10 +47,12 @@ public: std::list<boost::shared_ptr<LoadFontNode> > load_font_nodes () const; - void add_font (std::string id, std::string uri); + void add_font (std::string id, boost::filesystem::path file); Glib::ustring xml_as_string () const; void write (boost::filesystem::path path) const; + void resolve_fonts (std::list<boost::shared_ptr<Object> > objects); + void add_font_assets (std::list<boost::shared_ptr<Asset> >& assets); /** Set the reel number or sub-element identifier * of these subtitles. diff --git a/src/reel.cc b/src/reel.cc index 106fbf40..4d92d345 100644 --- a/src/reel.cc +++ b/src/reel.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 @@ -30,6 +30,7 @@ #include "reel_subtitle_asset.h" #include "decrypted_kdm_key.h" #include "decrypted_kdm.h" +#include "interop_subtitle_asset.h" #include <libxml++/nodes/element.h> using std::string; @@ -176,5 +177,11 @@ Reel::resolve_refs (list<shared_ptr<Object> > objects) if (_main_subtitle) { _main_subtitle->asset_ref().resolve (objects); + + /* Interop subtitle handling is all special cases */ + shared_ptr<InteropSubtitleAsset> iop = dynamic_pointer_cast<InteropSubtitleAsset> (_main_subtitle->asset_ref().object ()); + if (iop) { + iop->resolve_fonts (objects); + } } } diff --git a/src/smpte_subtitle_asset.cc b/src/smpte_subtitle_asset.cc index 69e2712f..28d8b261 100644 --- a/src/smpte_subtitle_asset.cc +++ b/src/smpte_subtitle_asset.cc @@ -209,3 +209,8 @@ SMPTESubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions return false; } +void +SMPTESubtitleAsset::add_font (string id, boost::filesystem::path file) +{ + /* XXX */ +} diff --git a/src/smpte_subtitle_asset.h b/src/smpte_subtitle_asset.h index 3fb2571a..37f58c6f 100644 --- a/src/smpte_subtitle_asset.h +++ b/src/smpte_subtitle_asset.h @@ -53,6 +53,7 @@ public: Glib::ustring xml_as_string () const; void write (boost::filesystem::path path) const; + void add_font (std::string id, boost::filesystem::path file); void set_content_title_text (std::string t) { _content_title_text = t; diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index 45177b95..70d7a955 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -29,6 +29,7 @@ #include "KM_util.h" #include <libxml++/nodes/element.h> #include <boost/algorithm/string.hpp> +#include <boost/shared_array.hpp> #include <fstream> using std::string; @@ -37,7 +38,9 @@ using std::ostream; using std::ofstream; using std::stringstream; using std::cout; +using std::cerr; using boost::shared_ptr; +using boost::shared_array; using boost::optional; using boost::dynamic_pointer_cast; using namespace dcp; @@ -304,4 +307,22 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* root, int time_code_rate, strin } } - +void +SubtitleAsset::add_font_data (string id, boost::filesystem::path file) +{ + boost::uintmax_t size = boost::filesystem::file_size (file); + FILE* f = fopen_boost (file, "r"); + if (!f) { + throw FileError ("could not open font file for reading", file, errno); + } + + shared_array<uint8_t> data (new uint8_t[size]); + size_t const read = fread (data.get(), 1, size, f); + fclose (f); + + if (read != size) { + throw FileError ("could not read font file", file, -1); + } + + _fonts[id] = FontData (data, size, file); +} diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 5fdb5f7a..481556aa 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -24,11 +24,14 @@ #include "dcp_time.h" #include "subtitle_string.h" #include <libcxml/cxml.h> +#include <boost/shared_array.hpp> namespace xmlpp { class Element; } +struct interop_dcp_font_test; + namespace dcp { @@ -64,6 +67,7 @@ public: } void add (SubtitleString); + virtual void add_font (std::string id, boost::filesystem::path file) = 0; virtual void write (boost::filesystem::path) const = 0; virtual Glib::ustring xml_as_string () const = 0; @@ -73,13 +77,40 @@ public: virtual std::list<boost::shared_ptr<LoadFontNode> > load_font_nodes () const = 0; protected: + friend struct ::interop_dcp_font_test; + void parse_subtitles (boost::shared_ptr<cxml::Document> xml, std::list<boost::shared_ptr<FontNode> > font_nodes); - void subtitles_as_xml (xmlpp::Element* root, int time_code_rate, std::string xmlns) const; + void add_font_data (std::string id, boost::filesystem::path file); /** All our subtitles, in no particular order */ std::list<SubtitleString> _subtitles; + class FontData { + public: + FontData () {} + + FontData (boost::shared_array<uint8_t> data_, boost::uintmax_t size_) + : data (data_) + , size (size_) + {} + + FontData (boost::shared_array<uint8_t> data_, boost::uintmax_t size_, boost::filesystem::path file_) + : data (data_) + , size (size_) + , file (file_) + {} + + boost::shared_array<uint8_t> data; + boost::uintmax_t size; + mutable boost::filesystem::path file; + }; + + /** Font data, keyed by a subclass-dependent identifier. + * For Interop fonts, the string is the font ID from the subtitle file. + */ + std::map<std::string, FontData> _fonts; + private: /** @struct ParseState * @brief A struct to hold state when parsing a subtitle XML file. |
