X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Frender_text.cc;h=9c1c233c26c12c1bf0202e4f2c9683c2eb3f00f9;hb=9726a58f44d52d235b027225ddd68c6acf83c733;hp=6f7614d36f5050b4bde1f9c553c59d5827110f7f;hpb=500f121343adb67fdbce10a41b1902ccdbbba1e2;p=dcpomatic.git diff --git a/src/lib/render_text.cc b/src/lib/render_text.cc index 6f7614d36..9c1c233c2 100644 --- a/src/lib/render_text.cc +++ b/src/lib/render_text.cc @@ -22,17 +22,17 @@ #include "cross.h" #include "dcpomatic_assert.h" #include "font.h" +#include "font_config.h" #include "image.h" #include "render_text.h" #include "types.h" #include "util.h" -#include "warnings.h" #include -#include +#include #include -DCPOMATIC_DISABLE_WARNINGS +LIBDCP_DISABLE_WARNINGS #include -DCPOMATIC_ENABLE_WARNINGS +LIBDCP_ENABLE_WARNINGS #include #include #include @@ -51,10 +51,6 @@ using std::string; using namespace dcpomatic; -static FcConfig* fc_config = nullptr; -static list> fc_config_fonts; - - /** Create a Pango layout using a dummy context which we can use to calculate the size * of the text we will render. Then we can transfer the layout over to the real context * for the actual render. @@ -99,7 +95,7 @@ marked_up (list subtitles, int target_height, float fade_factor, str if (subtitle.underline()) { span += "underline=\"single\" "; } - span += "size=\"" + dcp::raw_convert(subtitle.size_in_pixels(target_height) * pixels_to_1024ths_point) + "\" "; + span += "size=\"" + dcp::raw_convert(lrintf(subtitle.size_in_pixels(target_height) * pixels_to_1024ths_point)) + "\" "; /* Between 1-65535 inclusive, apparently... */ span += "alpha=\"" + dcp::raw_convert(int(floor(fade_factor * 65534)) + 1) + "\" "; span += "color=\"#" + subtitle.colour().to_rgb_string() + "\""; @@ -175,62 +171,15 @@ create_surface (shared_ptr image) static string -setup_font (StringText const& subtitle, list> const& fonts) +setup_font (StringText const& subtitle) { - if (!fc_config) { - fc_config = FcInitLoadConfig (); - } - auto font_file = default_font_file (); - for (auto i: fonts) { - if (i->id() == subtitle.font() && i->file()) { - font_file = i->file().get(); - } + if (subtitle.font && subtitle.font->file()) { + font_file = *subtitle.font->file(); } - auto existing = fc_config_fonts.cbegin (); - while (existing != fc_config_fonts.end() && existing->first != font_file) { - ++existing; - } - - string font_name; - if (existing != fc_config_fonts.end ()) { - font_name = existing->second; - } else { - /* Make this font available to DCP-o-matic */ - FcConfigAppFontAddFile (fc_config, reinterpret_cast(font_file.string().c_str())); - auto pattern = FcPatternBuild ( - 0, FC_FILE, FcTypeString, font_file.string().c_str(), static_cast(0) - ); - auto object_set = FcObjectSetBuild (FC_FAMILY, FC_STYLE, FC_LANG, FC_FILE, static_cast (0)); - auto font_set = FcFontList (fc_config, pattern, object_set); - if (font_set) { - for (int i = 0; i < font_set->nfont; ++i) { - FcPattern* font = font_set->fonts[i]; - FcChar8* file; - FcChar8* family; - FcChar8* style; - if ( - FcPatternGetString (font, FC_FILE, 0, &file) == FcResultMatch && - FcPatternGetString (font, FC_FAMILY, 0, &family) == FcResultMatch && - FcPatternGetString (font, FC_STYLE, 0, &style) == FcResultMatch - ) { - font_name = reinterpret_cast (family); - } - } - - FcFontSetDestroy (font_set); - } - - FcObjectSetDestroy (object_set); - FcPatternDestroy (pattern); - - fc_config_fonts.push_back (make_pair(font_file, font_name)); - } - - FcConfigSetCurrent (fc_config); - return font_name; + return FontConfig::instance()->make_font_available(font_file); } @@ -296,27 +245,41 @@ x_position (StringText const& first, int target_width, int layout_width) static int -y_position (StringText const& first, int target_height, int layout_height) +y_position (StringText const& first, int target_height, int baseline_to_bottom, int layout_height) { int y = 0; - switch (first.v_align()) { - case dcp::VAlign::TOP: - /* SMPTE says that v_position is the distance between top - of frame and top of subtitle, but this doesn't always seem to be - the case in practice; Gunnar Ásgeirsson's Dolby server appears - to put VAlign::TOP subs with v_position as the distance between top - of frame and bottom of subtitle. - */ - y = first.v_position() * target_height - layout_height; - break; - case dcp::VAlign::CENTER: - /* v_position is distance between centre of frame and centre of subtitle */ - y = (0.5 + first.v_position()) * target_height - layout_height / 2; - break; - case dcp::VAlign::BOTTOM: - /* v_position is distance between bottom of frame and bottom of subtitle */ - y = (1.0 - first.v_position()) * target_height - layout_height; + switch (first.valign_standard) { + case dcp::Standard::INTEROP: + switch (first.v_align()) { + case dcp::VAlign::TOP: + /* v_position is distance from top of frame to subtitle baseline */ + y = first.v_position() * target_height - (layout_height - baseline_to_bottom); + break; + case dcp::VAlign::CENTER: + /* v_position is distance from centre of frame to subtitle baseline */ + y = (0.5 + first.v_position()) * target_height - (layout_height - baseline_to_bottom); + break; + case dcp::VAlign::BOTTOM: + /* v_position is distance from bottom of frame to subtitle baseline */ + y = (1.0 - first.v_position()) * target_height - (layout_height - baseline_to_bottom); + break; + } break; + case dcp::Standard::SMPTE: + switch (first.v_align()) { + case dcp::VAlign::TOP: + /* v_position is distance from top of frame to top of subtitle */ + y = first.v_position() * target_height; + break; + case dcp::VAlign::CENTER: + /* v_position is distance from centre of frame to centre of subtitle */ + y = (0.5 + first.v_position()) * target_height - layout_height / 2; + break; + case dcp::VAlign::BOTTOM: + /* v_position is distance from bottom of frame to bottom of subtitle */ + y = (1.0 - first.v_position()) * target_height - layout_height; + break; + } } return y; @@ -327,7 +290,7 @@ y_position (StringText const& first, int target_height, int layout_height) * at the same time and with the same fade in/out. */ static PositionImage -render_line (list subtitles, list> fonts, dcp::Size target, DCPTime time, int frame_rate) +render_line (list subtitles, dcp::Size target, DCPTime time, int frame_rate) { /* XXX: this method can only handle italic / bold changes mid-line, nothing else yet. @@ -336,13 +299,13 @@ render_line (list subtitles, list> fonts, dcp::Size DCPOMATIC_ASSERT (!subtitles.empty ()); auto const& first = subtitles.front (); - auto const font_name = setup_font (first, fonts); + auto const font_name = setup_font (first); auto const fade_factor = calculate_fade_factor (first, time, frame_rate); auto const markup = marked_up (subtitles, target.height, fade_factor, font_name); auto layout = create_layout (); setup_layout (layout, font_name, markup); - dcp::Size size; - layout->get_pixel_size (size.width, size.height); + auto ink = layout->get_ink_extents(); + dcp::Size size{ink.get_width() / Pango::SCALE, ink.get_height() / Pango::SCALE}; /* Calculate x and y scale factors. These are only used to stretch the font away from its normal aspect ratio. @@ -367,12 +330,8 @@ render_line (list subtitles, list> fonts, dcp::Size size.height *= y_scale; /* Shuffle the subtitle over by the border width (if we have any) so it's not cut off */ - int const x_offset = ceil (border_width); - /* Move down a bit so that accents on capital letters can be seen */ - int const y_offset = target.height / 100.0; - - size.width += x_offset; - size.height += y_offset; + int const x_offset = (-ink.get_x() / Pango::SCALE) + ceil(border_width); + int const y_offset = -ink.get_y() / Pango::SCALE + ceil(border_width); auto image = create_image (size); auto surface = create_surface (image); @@ -414,7 +373,7 @@ render_line (list subtitles, list> fonts, dcp::Size context->stroke (); int const x = x_position (first, target.width, size.width); - int const y = y_position (first, target.height, size.height); + int const y = y_position (first, target.height, ink.get_y() / Pango::SCALE, size.height); return PositionImage (image, Position(max (0, x), max(0, y))); } @@ -424,21 +383,21 @@ render_line (list subtitles, list> fonts, dcp::Size * @param frame_rate DCP frame rate. */ list -render_text (list subtitles, list> fonts, dcp::Size target, DCPTime time, int frame_rate) +render_text (list subtitles, dcp::Size target, DCPTime time, int frame_rate) { list pending; list images; 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)) { - images.push_back (render_line (pending, fonts, target, time, frame_rate)); + images.push_back(render_line(pending, target, time, frame_rate)); pending.clear (); } pending.push_back (i); } if (!pending.empty()) { - images.push_back (render_line (pending, fonts, target, time, frame_rate)); + images.push_back(render_line(pending, target, time, frame_rate)); } return images;