+
+
+vector<dcpomatic::Rect<int>>
+bounding_box(vector<StringText> subtitles, dcp::Size target, optional<dcp::SubtitleStandard> override_standard)
+{
+ vector<StringText> pending;
+ vector<dcpomatic::Rect<int>> rects;
+
+ auto use_pending = [&pending, &rects, target, override_standard]() {
+ auto const& subtitle = pending.front();
+ auto standard = override_standard.get_value_or(subtitle.valign_standard);
+ /* We can provide dummy values for time and frame rate here as they are only used to calculate fades */
+ auto layout = setup_layout(pending, target, DCPTime(), 24);
+ int const x = x_position(subtitle.h_align(), subtitle.h_position(), target.width, layout.size.width);
+ auto const border_width = border_width_for_subtitle(subtitle, target);
+ int const y = y_position(standard, subtitle.v_align(), subtitle.v_position(), target.height, layout.baseline_to_bottom(border_width), layout.size.height);
+ rects.push_back({Position<int>(x, y), layout.size.width, layout.size.height});
+ };
+
+ for (auto const& i: subtitles) {
+ if (!pending.empty() && (i.v_align() != pending.back().v_align() || fabs(i.v_position() - pending.back().v_position()) > 1e-4)) {
+ use_pending();
+ pending.clear();
+ }
+ pending.push_back(i);
+ }
+
+ if (!pending.empty()) {
+ use_pending();
+ }
+
+ return rects;
+}
+
+
+float
+FontMetrics::height(StringText const& subtitle)
+{
+ return get(subtitle)->second.second;
+}
+
+
+float
+FontMetrics::baseline_to_bottom(StringText const& subtitle)
+{
+ return get(subtitle)->second.first;
+}
+
+
+FontMetrics::Cache::iterator
+FontMetrics::get(StringText const& subtitle)
+{
+ auto id = Identifier(subtitle);
+
+ auto iter = _cache.find(id);
+ if (iter != _cache.end()) {
+ return iter;
+ }
+
+ auto const font_name = FontConfig::instance()->make_font_available(subtitle.font);
+ auto copy = subtitle;
+ copy.set_text("Qypjg");
+ auto layout = create_layout(font_name, marked_up({copy}, _target_height, 1, font_name));
+ auto ink = layout->get_ink_extents();
+ auto const scale = float(_target_height * Pango::SCALE);
+ return _cache.insert({id, { ink.get_y() / scale, ink.get_height() / scale}}).first;
+}
+
+
+FontMetrics::Identifier::Identifier(StringText const& subtitle)
+ : font(subtitle.font)
+ , size(subtitle.size())
+ , aspect_adjust(subtitle.aspect_adjust())
+{
+
+}
+
+
+bool
+FontMetrics::Identifier::operator<(FontMetrics::Identifier const& other) const
+{
+ if (font != other.font) {
+ return font < other.font;
+ }
+
+ if (size != other.size) {
+ return size < other.size;
+ }
+
+ return aspect_adjust < other.aspect_adjust;
+}
+