Pass fonts from content around as FontData.
authorCarl Hetherington <cth@carlh.net>
Sun, 20 Dec 2020 22:41:52 +0000 (23:41 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 22 Dec 2020 01:37:53 +0000 (02:37 +0100)
i.e. as a block of memory rather than a file.  Also, get the
fonts from the decoder rather than the content.

Together, these changes allow us to use fonts from SMPTE DCPs
added as content.  Before, fonts would be messed up in those
cases (#1885).

20 files changed:
cscript
src/lib/dcp_decoder.cc
src/lib/dcp_decoder.h
src/lib/dcp_encoder.cc
src/lib/dcp_subtitle_decoder.cc
src/lib/dcp_subtitle_decoder.h
src/lib/decoder.h
src/lib/font_data.h
src/lib/hints.cc
src/lib/player.cc
src/lib/player.h
src/lib/reel_writer.cc
src/lib/reel_writer.h
src/lib/string_text_file_decoder.cc
src/lib/string_text_file_decoder.h
src/lib/subtitle_encoder.cc
src/lib/subtitle_encoder.h
src/lib/writer.cc
src/lib/writer.h
test/data

diff --git a/cscript b/cscript
index 634f343e8585e679a05524a9eec3a232bbc1fd73..4ae6490ab27ce6d5d302d4bfe498a86bc1bb8a09 100644 (file)
--- a/cscript
+++ b/cscript
@@ -375,8 +375,8 @@ def dependencies(target, options):
             (target.platform == 'osx' and target.bits == 64) or
             (target.platform == 'windows')) else {}
 
-    deps.append(('libdcp', '2b522d0', cpp_lib_options))
-    deps.append(('libsub', 'dcd8bf5', cpp_lib_options))
+    deps.append(('libdcp', 'c6665c1', cpp_lib_options))
+    deps.append(('libsub', '64eb116', cpp_lib_options))
     deps.append(('leqm-nrt', 'carl'))
     deps.append(('rtaudio', 'carl'))
     # We get our OpenSSL libraries from the environment, but we
index 758ddea2674174bc4e6d2b68c03811de481c6fc3..17710a3bd093a0127af3aec339d33cff6de0ffa6 100644 (file)
@@ -56,7 +56,9 @@
 
 using std::list;
 using std::cout;
+using std::map;
 using std::string;
+using std::vector;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 using boost::optional;
@@ -487,3 +489,20 @@ DCPDecoder::position () const
 {
        return ContentTime::from_frames(_offset, _dcp_content->active_video_frame_rate(film())) + _next;
 }
+
+
+vector<FontData>
+DCPDecoder::fonts () const
+{
+       vector<FontData> data;
+       BOOST_FOREACH (shared_ptr<dcp::Reel> i, _reels) {
+               if (i->main_subtitle() && i->main_subtitle()->asset()) {
+                       map<string, dcp::ArrayData> fm = i->main_subtitle()->asset()->font_data();
+                       for (map<string, dcp::ArrayData>::const_iterator j = fm.begin(); j != fm.end(); ++j) {
+                               data.push_back (FontData(j->first, j->second));
+                       }
+               }
+       }
+       return data;
+}
+
index 1abe39a27d7e56bf74bb8a58be4ec557f7b7d301..99bdb8bd4897491b5ea0feec40b13120d715423d 100644 (file)
@@ -59,6 +59,8 @@ public:
        bool pass ();
        void seek (dcpomatic::ContentTime t, bool accurate);
 
+       std::vector<dcpomatic::FontData> fonts () const;
+
        std::string lazy_digest () const {
                return _lazy_digest;
        }
index 1c5b00dd45e6c54d03a9d0407565f0158f670d98..c530492cf2275e98aae571f7908ae57e91516d52 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -46,6 +46,7 @@
 using std::string;
 using std::cout;
 using std::list;
+using std::vector;
 using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
@@ -103,13 +104,13 @@ DCPEncoder::go ()
        }
 
        if (_non_burnt_subtitles) {
-               list<shared_ptr<Font> > fonts = _player->get_subtitle_fonts ();
+               vector<FontData> fonts = _player->get_subtitle_fonts ();
 
                if (fonts.size() > 1 && _film->interop()) {
                        /* Interop will ignore second and subsequent <LoadFont>s so don't even
                           write them as they upset some validators.
                        */
-                       shared_ptr<Font> first = fonts.front ();
+                       FontData first = fonts.front ();
                        fonts.clear ();
                        fonts.push_back (first);
                }
index f34c495c0eb03eaf3621ae1b533e70b958b6bc6e..16a738a5135eedc5407e55f6185554faefc14d1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2014-2018 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 #include "dcp_subtitle_decoder.h"
 #include "dcp_subtitle_content.h"
 #include <dcp/interop_subtitle_asset.h>
+#include <dcp/load_font_node.h>
 #include <iostream>
 
-using std::list;
 using std::cout;
+using std::list;
+using std::map;
+using std::string;
+using std::vector;
 using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 using boost::bind;
@@ -43,6 +47,18 @@ DCPSubtitleDecoder::DCPSubtitleDecoder (shared_ptr<const Film> film, shared_ptr<
                first = content_time_period(*_next).from;
        }
        text.push_back (shared_ptr<TextDecoder> (new TextDecoder (this, content->only_text(), first)));
+
+       map<string, dcp::ArrayData> fm = c->font_data();
+       for (map<string, dcp::ArrayData>::const_iterator j = fm.begin(); j != fm.end(); ++j) {
+               _fonts.push_back (FontData(j->first, j->second));
+       }
+
+       /* Add a default font for any LoadFont nodes in our file which we haven't yet found fonts for */
+       BOOST_FOREACH (shared_ptr<dcp::LoadFontNode> i, c->load_font_nodes()) {
+               if (fm.find(i->id) == fm.end()) {
+                       _fonts.push_back (FontData(i->id, dcp::ArrayData(default_font_file())));
+               }
+       }
 }
 
 void
@@ -105,3 +121,11 @@ DCPSubtitleDecoder::content_time_period (shared_ptr<dcp::Subtitle> s) const
                ContentTime::from_seconds (s->out().as_seconds ())
                );
 }
+
+
+vector<dcpomatic::FontData>
+DCPSubtitleDecoder::fonts () const
+{
+       return _fonts;
+}
+
index 5bf6363ad282630005a81067e0ac1940179e5cd9..b53b88dedab7806eaa12b6c8ba6dc6d20641dabe 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -20,6 +20,7 @@
 
 #include "text_decoder.h"
 #include "dcp_subtitle.h"
+#include "font_data.h"
 
 class DCPSubtitleContent;
 
@@ -31,9 +32,13 @@ public:
        bool pass ();
        void seek (dcpomatic::ContentTime time, bool accurate);
 
+       std::vector<dcpomatic::FontData> fonts () const;
+
 private:
        dcpomatic::ContentTimePeriod content_time_period (boost::shared_ptr<dcp::Subtitle> s) const;
 
        std::list<boost::shared_ptr<dcp::Subtitle> > _subtitles;
        std::list<boost::shared_ptr<dcp::Subtitle> >::const_iterator _next;
+
+       std::vector<dcpomatic::FontData> _fonts;
 };
index 97de208b266b7ea3a95fd839f7dcb16f4edd66c5..169d55553ee93754c9978afafba1430b5da81f29 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "types.h"
 #include "film.h"
+#include "font_data.h"
 #include "dcpomatic_time.h"
 #include "weak_film.h"
 #include <boost/utility.hpp>
@@ -61,6 +62,10 @@ public:
        virtual void seek (dcpomatic::ContentTime time, bool accurate);
 
        virtual dcpomatic::ContentTime position () const;
+
+       virtual std::vector<dcpomatic::FontData> fonts () const {
+               return std::vector<dcpomatic::FontData>();
+       }
 };
 
 #endif
index 90543bec91ff613c45762a992b4b46bc3f8968c6..686fca7c973e21fde47534d07ec203bb8cae3b4b 100644 (file)
 */
 
 
+#ifndef DCPOMATIC_FONT_DATA_H
+#define DCPOMATIC_FONT_DATA_H
+
+
 #include <dcp/array_data.h>
 #include <boost/optional.hpp>
 #include <string>
@@ -51,3 +55,6 @@ extern bool operator!= (FontData const& a, FontData const& b);
 
 
 }
+
+
+#endif
index ffe6d8e73b131f77600518d38d50de720b46ea90..9781f24bb9e01bcd0cf1bc86094bda48248be2dc 100644 (file)
@@ -27,6 +27,7 @@
 #include "text_content.h"
 #include "audio_processor.h"
 #include "font.h"
+#include "font_data.h"
 #include "ratio.h"
 #include "audio_analysis.h"
 #include "compose.hpp"
index 7899f2e83eb4139f62157399608e59dd063c50ca..dd11694ef4687477f567033bd95b29d2e136ef15 100644 (file)
@@ -448,20 +448,18 @@ Player::content_time_to_dcp (shared_ptr<const Piece> piece, ContentTime t) const
        return max (DCPTime (), DCPTime (t - piece->content->trim_start(), piece->frc) + piece->content->position());
 }
 
-list<shared_ptr<Font> >
+vector<FontData>
 Player::get_subtitle_fonts ()
 {
        boost::mutex::scoped_lock lm (_mutex);
 
-       list<shared_ptr<Font> > fonts;
+       vector<FontData> fonts;
        BOOST_FOREACH (shared_ptr<Piece> i, _pieces) {
-               BOOST_FOREACH (shared_ptr<TextContent> j, i->content->text) {
-                       /* XXX: things may go wrong if there are duplicate font IDs
-                          with different font files.
-                       */
-                       list<shared_ptr<Font> > f = j->fonts ();
-                       copy (f.begin(), f.end(), back_inserter (fonts));
-               }
+               /* XXX: things may go wrong if there are duplicate font IDs
+                  with different font files.
+               */
+               vector<FontData> f = i->decoder->fonts ();
+               copy (f.begin(), f.end(), back_inserter(fonts));
        }
 
        return fonts;
index ea81ae939bb85e181e557502e1258921543f8849..c695e02cde177a5a1f0a378c509ac36a1913862b 100644 (file)
@@ -45,7 +45,7 @@ namespace dcp {
 }
 
 namespace dcpomatic {
-       class Font;
+       class FontData;
 }
 
 class AtmosContent;
@@ -79,7 +79,7 @@ public:
        bool pass ();
        void seek (dcpomatic::DCPTime time, bool accurate);
 
-       std::list<boost::shared_ptr<dcpomatic::Font> > get_subtitle_fonts ();
+       std::vector<dcpomatic::FontData> get_subtitle_fonts ();
        std::list<ReferencedReelAsset> get_reel_assets ();
        dcp::Size video_container_size () const {
                boost::mutex::scoped_lock lm (_mutex);
index 41de4481ed3e11e3d01cc340ef103850c95f4c4f..009b2dc1516aa98df6ee64320a3c7d207f6614f3 100644 (file)
@@ -25,7 +25,7 @@
 #include "log.h"
 #include "dcpomatic_log.h"
 #include "digester.h"
-#include "font.h"
+#include "font_data.h"
 #include "compose.hpp"
 #include "config.h"
 #include "audio_buffers.h"
@@ -192,6 +192,8 @@ ReelWriter::ReelWriter (
                        film()->contains_atmos_content()
                        );
        }
+
+       _default_font = dcp::ArrayData(default_font_file());
 }
 
 /** @param frame reel-relative frame */
@@ -444,7 +446,8 @@ maybe_add_text (
        int64_t picture_duration,
        shared_ptr<dcp::Reel> reel,
        list<ReferencedReelAsset> const & refs,
-       list<shared_ptr<Font> > const & fonts,
+       vector<FontData> const & fonts,
+       dcp::ArrayData default_font,
        shared_ptr<const Film> film,
        DCPTimePeriod period,
        boost::filesystem::path output_dcp,
@@ -457,8 +460,8 @@ maybe_add_text (
 
        if (asset) {
                /* Add the font to the subtitle content */
-               BOOST_FOREACH (shared_ptr<Font> j, fonts) {
-                       asset->add_font (j->id(), j->file().get_value_or(default_font_file()));
+               BOOST_FOREACH (FontData const& j, fonts) {
+                       asset->add_font (j.id, j.data.get_value_or(default_font));
                }
 
                if (dynamic_pointer_cast<dcp::InteropSubtitleAsset> (asset)) {
@@ -615,7 +618,7 @@ void
 ReelWriter::create_reel_text (
        shared_ptr<dcp::Reel> reel,
        list<ReferencedReelAsset> const & refs,
-       list<shared_ptr<Font> > const& fonts,
+       vector<FontData> const& fonts,
        int64_t duration,
        boost::filesystem::path output_dcp,
        bool ensure_subtitles,
@@ -623,7 +626,7 @@ ReelWriter::create_reel_text (
        ) const
 {
        shared_ptr<dcp::ReelSubtitleAsset> subtitle = maybe_add_text<dcp::ReelSubtitleAsset> (
-               _subtitle_asset, duration, reel, refs, fonts, film(), _period, output_dcp, _text_only
+               _subtitle_asset, duration, reel, refs, fonts, _default_font, film(), _period, output_dcp, _text_only
                );
 
        if (subtitle) {
@@ -639,6 +642,7 @@ ReelWriter::create_reel_text (
                        reel,
                        refs,
                        fonts,
+                       _default_font,
                        film(),
                        _period,
                        output_dcp,
@@ -648,7 +652,7 @@ ReelWriter::create_reel_text (
 
        for (map<DCPTextTrack, shared_ptr<dcp::SubtitleAsset> >::const_iterator i = _closed_caption_assets.begin(); i != _closed_caption_assets.end(); ++i) {
                shared_ptr<dcp::ReelClosedCaptionAsset> a = maybe_add_text<dcp::ReelClosedCaptionAsset> (
-                       i->second, duration, reel, refs, fonts, film(), _period, output_dcp, _text_only
+                       i->second, duration, reel, refs, fonts, _default_font, film(), _period, output_dcp, _text_only
                        );
                DCPOMATIC_ASSERT (a);
                a->set_annotation_text (i->first.name);
@@ -662,7 +666,7 @@ ReelWriter::create_reel_text (
        /* Make empty tracks for anything we've been asked to ensure but that we haven't added */
        BOOST_FOREACH (DCPTextTrack i, ensure_closed_captions) {
                shared_ptr<dcp::ReelClosedCaptionAsset> a = maybe_add_text<dcp::ReelClosedCaptionAsset> (
-                       empty_text_asset(TEXT_CLOSED_CAPTION, i), duration, reel, refs, fonts, film(), _period, output_dcp, _text_only
+                       empty_text_asset(TEXT_CLOSED_CAPTION, i), duration, reel, refs, fonts, _default_font, film(), _period, output_dcp, _text_only
                        );
                DCPOMATIC_ASSERT (a);
                a->set_annotation_text (i.name);
@@ -705,7 +709,7 @@ ReelWriter::create_reel_markers (shared_ptr<dcp::Reel> reel) const
 shared_ptr<dcp::Reel>
 ReelWriter::create_reel (
        list<ReferencedReelAsset> const & refs,
-       list<shared_ptr<Font> > const & fonts,
+       vector<FontData> const & fonts,
        boost::filesystem::path output_dcp,
        bool ensure_subtitles,
        set<DCPTextTrack> ensure_closed_captions
index 3884942479d6b898bef77bf21dd1236af60b01aa..3d214878b5d71b5de89d07d8bdde31928712b0f9 100644 (file)
@@ -31,7 +31,7 @@
 #include <boost/weak_ptr.hpp>
 
 namespace dcpomatic {
-       class Font;
+       class FontData;
 }
 
 class Film;
@@ -78,7 +78,7 @@ public:
        void finish (boost::filesystem::path output_dcp);
        boost::shared_ptr<dcp::Reel> create_reel (
                std::list<ReferencedReelAsset> const & refs,
-               std::list<boost::shared_ptr<dcpomatic::Font> > const & fonts,
+               std::vector<dcpomatic::FontData> const & fonts,
                boost::filesystem::path output_dcp,
                bool ensure_subtitles,
                std::set<DCPTextTrack> ensure_closed_captions
@@ -111,7 +111,8 @@ private:
        void create_reel_sound (boost::shared_ptr<dcp::Reel> reel, std::list<ReferencedReelAsset> const & refs) const;
        void create_reel_text (
                boost::shared_ptr<dcp::Reel> reel,
-               std::list<ReferencedReelAsset> const & refs, std::list<boost::shared_ptr<dcpomatic::Font> > const& fonts,
+               std::list<ReferencedReelAsset> const & refs,
+               std::vector<dcpomatic::FontData> const& fonts,
                int64_t duration,
                boost::filesystem::path output_dcp,
                bool ensure_subtitles,
@@ -132,6 +133,8 @@ private:
        boost::weak_ptr<Job> _job;
        bool _text_only;
 
+       dcp::ArrayData _default_font;
+
        boost::shared_ptr<dcp::PictureAsset> _picture_asset;
        /** picture asset writer, or 0 if we are not writing any picture because we already have one */
        boost::shared_ptr<dcp::PictureAssetWriter> _picture_asset_writer;
index 4cf34a3a94c31ace9c56d4ba4547587cd2ceab58..691734d7bbf11d1d218efa139dc3eb01b44c6e2d 100644 (file)
@@ -89,3 +89,17 @@ StringTextFileDecoder::content_time_period (sub::Subtitle s) const
                ContentTime::from_seconds (s.to.all_as_seconds())
                );
 }
+
+
+vector<FontData>
+StringTextFileDecoder::fonts () const
+{
+       vector<FontData> data;
+       BOOST_FOREACH (shared_ptr<TextDecoder> i, text) {
+               BOOST_FOREACH (shared_ptr<Font> j, i->content()->fonts()) {
+                       data.push_back (FontData(j));
+               }
+       }
+       return data;
+}
+
index 0c1d31deb1661f78508a6a056b2fb0218642ce33..c57f40d24a7f5c8352f2dc7c6c31338b1bcf4dc7 100644 (file)
@@ -34,6 +34,8 @@ public:
        void seek (dcpomatic::ContentTime time, bool accurate);
        bool pass ();
 
+       std::vector<dcpomatic::FontData> fonts () const;
+
 private:
        dcpomatic::ContentTimePeriod content_time_period (sub::Subtitle s) const;
 
index b018dcfb429a47073a946cff59298bfbc1a48730..473d0698b2d6a80a8d59e1b8d00eefbdeff2cb01 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2019 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2019-2020 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -18,7 +18,7 @@
 
 */
 
-#include "font.h"
+#include "font_data.h"
 #include "subtitle_encoder.h"
 #include "player.h"
 #include "compose.hpp"
@@ -81,6 +81,8 @@ SubtitleEncoder::SubtitleEncoder (shared_ptr<const Film> film, shared_ptr<Job> j
        BOOST_FOREACH (dcpomatic::DCPTimePeriod i, film->reels()) {
                _reels.push_back (i);
        }
+
+       _default_font = dcp::ArrayData (default_font_file());
 }
 
 void
@@ -114,8 +116,8 @@ SubtitleEncoder::go ()
                }
 
                if (!_film->interop() || _include_font) {
-                       BOOST_FOREACH (shared_ptr<dcpomatic::Font> j, _player->get_subtitle_fonts()) {
-                               i->first->add_font (j->id(), default_font_file());
+                       BOOST_FOREACH (dcpomatic::FontData j, _player->get_subtitle_fonts()) {
+                               i->first->add_font (j.id, _default_font);
                        }
                }
 
index 6484d1b0bb63ccfb66983abecb90f2f3c0f8e44c..70b92456464e3312be9b667ecce9ab2f3afe4f1e 100644 (file)
@@ -58,4 +58,5 @@ private:
        int _reel_index;
        boost::optional<dcpomatic::DCPTime> _last;
        dcpomatic::DCPTime _length;
+       dcp::ArrayData _default_font;
 };
index fcf084c56e4fe276b6b267a534196d257938554c..77a6bb589183de5e159898204617eeab3b7d156c 100644 (file)
@@ -32,7 +32,7 @@
 #include "cross.h"
 #include "audio_buffers.h"
 #include "version.h"
-#include "font.h"
+#include "font_data.h"
 #include "util.h"
 #include "reel_writer.h"
 #include "text_content.h"
@@ -792,14 +792,14 @@ Writer::write (PlayerText text, TextType type, optional<DCPTextTrack> track, DCP
 }
 
 void
-Writer::write (list<shared_ptr<Font> > fonts)
+Writer::write (vector<FontData> fonts)
 {
        /* Just keep a list of unique fonts and we'll deal with them in ::finish */
 
-       BOOST_FOREACH (shared_ptr<Font> i, fonts) {
+       BOOST_FOREACH (FontData const& i, fonts) {
                bool got = false;
-               BOOST_FOREACH (shared_ptr<Font> j, _fonts) {
-                       if (*i == *j) {
+               BOOST_FOREACH (FontData const& j, _fonts) {
+                       if (i == j) {
                                got = true;
                        }
                }
index 52cb222e76c4c1bc2791340b9f1d4d2512204644..b924337ddfac1cd50bd9a85b88d4b32b1be41a1d 100644 (file)
@@ -40,7 +40,7 @@ namespace dcp {
 }
 
 namespace dcpomatic {
-       class Font;
+       class FontData;
 }
 
 class Film;
@@ -112,7 +112,7 @@ public:
        void repeat (Frame, Eyes);
        void write (boost::shared_ptr<const AudioBuffers>, dcpomatic::DCPTime time);
        void write (PlayerText text, TextType type, boost::optional<DCPTextTrack>, dcpomatic::DCPTimePeriod period);
-       void write (std::list<boost::shared_ptr<dcpomatic::Font> > fonts);
+       void write (std::vector<dcpomatic::FontData> fonts);
        void write (ReferencedReelAsset asset);
        void write (boost::shared_ptr<const dcp::AtmosFrame> atmos, dcpomatic::DCPTime time, AtmosMetadata metadata);
        void finish (boost::filesystem::path output_dcp);
@@ -196,7 +196,7 @@ private:
 
        std::list<ReferencedReelAsset> _reel_assets;
 
-       std::list<boost::shared_ptr<dcpomatic::Font> > _fonts;
+       std::vector<dcpomatic::FontData> _fonts;
 
        /** true if any reel has any subtitles */
        bool _have_subtitles;
index 578c16ee95b416d4dcec31c72219dac91e632169..8a1b08134f51c1172abd177eb64a4c790f854833 160000 (submodule)
--- a/test/data
+++ b/test/data
@@ -1 +1 @@
-Subproject commit 578c16ee95b416d4dcec31c72219dac91e632169
+Subproject commit 8a1b08134f51c1172abd177eb64a4c790f854833