Basically-working interop subtitle font handling.
[libdcp.git] / src / subtitle_asset.h
1 /*
2     Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifndef LIBDCP_SUBTITLE_ASSET_H
21 #define LIBDCP_SUBTITLE_ASSET_H
22
23 #include "asset.h"
24 #include "dcp_time.h"
25 #include "subtitle_string.h"
26 #include <libcxml/cxml.h>
27 #include <boost/shared_array.hpp>
28
29 namespace xmlpp {
30         class Element;
31 }
32
33 struct interop_dcp_font_test;
34
35 namespace dcp
36 {
37
38 class SubtitleString;   
39 class FontNode;
40 class TextNode;
41 class SubtitleNode;
42 class LoadFontNode;
43
44 /** @class SubtitleAsset
45  *  @brief A parent for classes representing a file containing subtitles.
46  *
47  *  This class holds a list of SubtitleString objects which it can extract
48  *  from the appropriate part of either an Interop or SMPTE XML file.
49  *  Its subclasses InteropSubtitleAsset and SMPTESubtitleAsset handle the
50  *  differences between the two types.
51  */
52 class SubtitleAsset : public Asset
53 {
54 public:
55         SubtitleAsset ();
56         SubtitleAsset (boost::filesystem::path file);
57
58         bool equals (
59                 boost::shared_ptr<const Asset>,
60                 EqualityOptions,
61                 NoteHandler note
62                 ) const;
63
64         std::list<SubtitleString> subtitles_during (Time from, Time to) const;
65         std::list<SubtitleString> const & subtitles () const {
66                 return _subtitles;
67         }
68
69         void add (SubtitleString);
70         virtual void add_font (std::string id, boost::filesystem::path file) = 0;
71
72         virtual void write (boost::filesystem::path) const = 0;
73         virtual Glib::ustring xml_as_string () const = 0;
74
75         Time latest_subtitle_out () const;
76
77         virtual std::list<boost::shared_ptr<LoadFontNode> > load_font_nodes () const = 0;
78
79 protected:
80         friend struct ::interop_dcp_font_test;
81         
82         void parse_subtitles (boost::shared_ptr<cxml::Document> xml, std::list<boost::shared_ptr<FontNode> > font_nodes);
83         void subtitles_as_xml (xmlpp::Element* root, int time_code_rate, std::string xmlns) const;
84         void add_font_data (std::string id, boost::filesystem::path file);
85
86         /** All our subtitles, in no particular order */
87         std::list<SubtitleString> _subtitles;
88
89         class FontData {
90         public:
91                 FontData () {}
92                 
93                 FontData (boost::shared_array<uint8_t> data_, boost::uintmax_t size_)
94                         : data (data_)
95                         , size (size_)
96                 {}
97
98                 FontData (boost::shared_array<uint8_t> data_, boost::uintmax_t size_, boost::filesystem::path file_)
99                         : data (data_)
100                         , size (size_)
101                         , file (file_)
102                 {}
103                 
104                 boost::shared_array<uint8_t> data;
105                 boost::uintmax_t size;
106                 mutable boost::filesystem::path file;
107         };
108
109         /** Font data, keyed by a subclass-dependent identifier.
110          *  For Interop fonts, the string is the font ID from the subtitle file.
111          */
112         std::map<std::string, FontData> _fonts;
113         
114 private:
115         /** @struct ParseState
116          *  @brief  A struct to hold state when parsing a subtitle XML file.
117          */
118         struct ParseState {
119                 std::list<boost::shared_ptr<FontNode> > font_nodes;
120                 std::list<boost::shared_ptr<TextNode> > text_nodes;
121                 std::list<boost::shared_ptr<SubtitleNode> > subtitle_nodes;
122         };
123
124         void maybe_add_subtitle (std::string text, ParseState const & parse_state);
125         
126         void examine_font_nodes (
127                 boost::shared_ptr<const cxml::Node> xml,
128                 std::list<boost::shared_ptr<FontNode> > const & font_nodes,
129                 ParseState& parse_state
130                 );
131         
132         void examine_text_nodes (
133                 boost::shared_ptr<const cxml::Node> xml,
134                 std::list<boost::shared_ptr<TextNode> > const & text_nodes,
135                 ParseState& parse_state
136                 );
137 };
138
139 }
140
141 #endif