Skip to content

Commit 57464a4

Browse files
committed
Add support for italics in subtitles
1 parent b853c39 commit 57464a4

9 files changed

+149
-45
lines changed

OMXPlayerSubtitles.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ OMXPlayerSubtitles::~OMXPlayerSubtitles() BOOST_NOEXCEPT
5757
bool OMXPlayerSubtitles::Open(size_t stream_count,
5858
vector<Subtitle>&& external_subtitles,
5959
const string& font_path,
60+
const string& italic_font_path,
6061
float font_size,
6162
bool centered,
6263
unsigned int lines,
@@ -75,6 +76,7 @@ bool OMXPlayerSubtitles::Open(size_t stream_count,
7576
m_thread_stopped.store(false, memory_order_relaxed);
7677

7778
m_font_path = font_path;
79+
m_italic_font_path = italic_font_path;
7880
m_font_size = font_size;
7981
m_centered = centered;
8082
m_lines = lines;
@@ -112,7 +114,8 @@ void OMXPlayerSubtitles::Process()
112114
{
113115
try
114116
{
115-
RenderLoop(m_font_path, m_font_size, m_centered, m_lines, m_av_clock);
117+
RenderLoop(m_font_path, m_italic_font_path, m_font_size, m_centered,
118+
m_lines, m_av_clock);
116119
}
117120
catch(Enforce_error& e)
118121
{
@@ -144,13 +147,15 @@ Iterator FindSubtitle(Iterator begin, Iterator end, int time)
144147

145148
void OMXPlayerSubtitles::
146149
RenderLoop(const string& font_path,
150+
const string& italic_font_path,
147151
float font_size,
148152
bool centered,
149153
unsigned int lines,
150154
OMXClock* clock)
151155
{
152156
SubtitleRenderer renderer(1,
153157
font_path,
158+
italic_font_path,
154159
font_size,
155160
0.01f, 0.06f,
156161
centered,

OMXPlayerSubtitles.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class OMXPlayerSubtitles : public OMXThread
4141
bool Open(size_t stream_count,
4242
std::vector<Subtitle>&& external_subtitles,
4343
const std::string& font_path,
44+
const std::string& italic_font_path,
4445
float font_size,
4546
bool centered,
4647
unsigned int lines,
@@ -112,6 +113,7 @@ class OMXPlayerSubtitles : public OMXThread
112113

113114
void Process();
114115
void RenderLoop(const std::string& font_path,
116+
const std::string& italic_font_path,
115117
float font_size,
116118
bool centered,
117119
unsigned int lines,
@@ -135,6 +137,7 @@ class OMXPlayerSubtitles : public OMXThread
135137
int m_delay;
136138
std::atomic<bool> m_thread_stopped;
137139
std::string m_font_path;
140+
std::string m_italic_font_path;
138141
float m_font_size;
139142
bool m_centered;
140143
unsigned int m_lines;

OMXSubtitleTagSami.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ void COMXSubtitleTagSami::ConvertLine(COMXOverlayText* pOverlay, const char* lin
7676
else if (fullTag == "<i>" || fullTag == "{\\i1}")
7777
{
7878
m_flag[FLAG_ITALIC] = true;
79-
// strUTF8.insert(pos, "[I]");
79+
strUTF8.insert(pos, "<i>");
8080
pos += 3;
8181
}
8282
else if ((fullTag == "</i>" || fullTag == "{\\i0}") && m_flag[FLAG_ITALIC])
8383
{
8484
m_flag[FLAG_ITALIC] = false;
85-
// strUTF8.insert(pos, "[/I]");
85+
strUTF8.insert(pos, "</i>");
8686
pos += 4;
8787
}
8888
else if ((fullTag == "</font>" || fullTag == "{\\c}") && m_flag[FLAG_COLOR])

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ Using OMXPlayer
7070
--subtitles path external subtitles in UTF-8 srt format
7171
--font path subtitle font
7272
(default: /usr/share/fonts/truetype/freefont/FreeSans.ttf)
73+
--italic-font path (default: /usr/share/fonts/truetype/freefont/FreeSansOblique.ttf)
7374
--font-size size font size as thousandths of screen height
7475
(default: 55)
7576
--align left/center subtitle alignment (default: left)

SubtitleRenderer.cpp

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ class BoxRenderer {
8888
}
8989
};
9090

91-
void SubtitleRenderer::load_glyph(char32_t codepoint) {
91+
void SubtitleRenderer::load_glyph(InternalChar ch) {
9292
VGfloat escapement[2]{};
9393

9494
auto load_glyph_internal =
9595
[&](FT_Face ft_face, VGFont vg_font, bool border) {
9696
try {
97-
auto glyph_index = FT_Get_Char_Index(ft_face, codepoint);
97+
auto glyph_index = FT_Get_Char_Index(ft_face, ch.codepoint());
9898
ENFORCE(!FT_Load_Glyph(ft_face, glyph_index, FT_LOAD_NO_HINTING));
9999

100100
FT_Glyph glyph;
@@ -165,7 +165,7 @@ void SubtitleRenderer::load_glyph(char32_t codepoint) {
165165
escapement[0] = static_cast<VGfloat>((ft_face->glyph->advance.x + 32) / 64);
166166
escapement[1] = 0;
167167

168-
vgSetGlyphToImage(vg_font, codepoint, image, glyph_origin, escapement);
168+
vgSetGlyphToImage(vg_font, ch.val, image, glyph_origin, escapement);
169169
assert(!vgGetError());
170170

171171
if (image) {
@@ -175,34 +175,40 @@ void SubtitleRenderer::load_glyph(char32_t codepoint) {
175175
} catch(...) {
176176
escapement[0] = 0;
177177
escapement[1] = 0;
178-
vgSetGlyphToImage(vg_font, codepoint, VG_INVALID_HANDLE, escapement, escapement);
178+
vgSetGlyphToImage(vg_font, ch.val, VG_INVALID_HANDLE, escapement, escapement);
179179
assert(!vgGetError());
180180
}
181181
};
182182

183-
load_glyph_internal(ft_face_, vg_font_, false);
184-
glyphs_[codepoint].advance = escapement[0];
185-
load_glyph_internal(ft_face_, vg_font_border_, true);
183+
if (!ch.italic()) {
184+
load_glyph_internal(ft_face_, vg_font_, false);
185+
glyphs_[ch].advance = escapement[0];
186+
load_glyph_internal(ft_face_, vg_font_border_, true);
187+
} else {
188+
load_glyph_internal(ft_face_italic_, vg_font_, false);
189+
glyphs_[ch].advance = escapement[0];
190+
load_glyph_internal(ft_face_italic_, vg_font_border_, true);
191+
}
186192
}
187193

188194
int SubtitleRenderer::get_text_width(const std::vector<InternalChar>& text) {
189195
int width = 0;
190196
for (auto c = text.begin(); c != text.end(); ++c) {
191-
width += c->italic ? (assert(0), 0)
192-
: glyphs_.at(c->codepoint).advance;
197+
width += glyphs_.at(*c).advance;
193198
}
194199
return width;
195200
}
196201

197202
std::vector<SubtitleRenderer::InternalChar> SubtitleRenderer::
198-
get_internal_chars(const std::string& str) {
203+
get_internal_chars(const std::string& str, TagTracker& tag_tracker) {
199204
std::vector<InternalChar> internal_chars;
200-
bool italic{};
201205
auto c_str = str.c_str();
202206
for (size_t i = 0, len = str.length(); i < len;) {
203207
try {
204208
auto cp = decodeUtf8(c_str, len, i);
205-
internal_chars.push_back(InternalChar({cp, italic}));
209+
tag_tracker.put(cp);
210+
if (!tag_tracker.in_tag())
211+
internal_chars.push_back(InternalChar(cp, tag_tracker.italic()));
206212
} catch (...) {
207213
++i; // Keep going
208214
}
@@ -213,14 +219,13 @@ get_internal_chars(const std::string& str) {
213219
void SubtitleRenderer::
214220
prepare_glyphs(const std::vector<InternalChar>& text) {
215221
for (auto c = text.begin(); c != text.end(); ++c) {
216-
if (glyphs_.find(c->codepoint) == glyphs_.end()) {
217-
load_glyph(c->codepoint);
218-
}
222+
if (glyphs_.find(*c) == glyphs_.end())
223+
load_glyph(*c);
219224
}
220225
}
221226

222227
void SubtitleRenderer::
223-
draw_text(VGFont font, VGFont italic_font,
228+
draw_text(VGFont font,
224229
const std::vector<SubtitleRenderer::InternalChar>& text,
225230
int x, int y,
226231
unsigned int lightness) {
@@ -245,10 +250,7 @@ draw_text(VGFont font, VGFont italic_font,
245250
assert(!vgGetError());
246251

247252
for (auto c = text.begin(); c != text.end(); ++c) {
248-
vgDrawGlyph(c->italic ? italic_font : font,
249-
c->codepoint,
250-
VG_FILL_PATH,
251-
VG_FALSE);
253+
vgDrawGlyph(font, c->val, VG_FILL_PATH, VG_FALSE);
252254
assert(!vgGetError());
253255
}
254256
}
@@ -261,6 +263,7 @@ SubtitleRenderer::~SubtitleRenderer() BOOST_NOEXCEPT {
261263
SubtitleRenderer::
262264
SubtitleRenderer(int layer,
263265
const std::string& font_path,
266+
const std::string& italic_font_path,
264267
float font_size,
265268
float margin_left,
266269
float margin_bottom,
@@ -276,10 +279,9 @@ SubtitleRenderer(int layer,
276279
surface_(),
277280
vg_font_(),
278281
vg_font_border_(),
279-
vg_font_italic_(),
280-
vg_font_italic_border_(),
281282
ft_library_(),
282283
ft_face_(),
284+
ft_face_italic_(),
283285
ft_stroker_(),
284286
line_height_(),
285287
box_offset_(),
@@ -296,7 +298,7 @@ SubtitleRenderer(int layer,
296298
uint32_t screen_width, screen_height;
297299
ENFORCE(graphics_get_display_size(0, &screen_width, &screen_height) >= 0);
298300

299-
initialize_fonts(font_path, font_size*screen_height);
301+
initialize_fonts(font_path, italic_font_path, font_size*screen_height);
300302

301303
int abs_margin_bottom =
302304
static_cast<int>(margin_bottom * screen_height + 0.5f) - box_offset_;
@@ -333,11 +335,16 @@ void SubtitleRenderer::destroy() {
333335
}
334336

335337
void SubtitleRenderer::
336-
initialize_fonts(const std::string& font_path, unsigned int font_size) {
338+
initialize_fonts(const std::string& font_path,
339+
const std::string& italic_font_path,
340+
unsigned int font_size) {
337341
ENFORCE(!FT_Init_FreeType(&ft_library_));
338342
ENFORCE2(!FT_New_Face(ft_library_, font_path.c_str(), 0, &ft_face_),
339343
"Unable to open font");
344+
ENFORCE2(!FT_New_Face(ft_library_, italic_font_path.c_str(), 0, &ft_face_italic_),
345+
"Unable to open italic font");
340346
ENFORCE(!FT_Set_Pixel_Sizes(ft_face_, 0, font_size));
347+
ENFORCE(!FT_Set_Pixel_Sizes(ft_face_italic_, 0, font_size));
341348

342349
auto get_bbox = [this](char32_t cp) {
343350
auto glyph_index = FT_Get_Char_Index(ft_face_, cp);
@@ -376,6 +383,7 @@ void SubtitleRenderer::destroy_fonts() {
376383
assert(!error);
377384
ft_library_ = {};
378385
ft_face_ = {};
386+
ft_face_italic_ = {};
379387
ft_stroker_ = {};
380388
}
381389
}
@@ -522,12 +530,13 @@ void SubtitleRenderer::destroy_vg() {
522530
void SubtitleRenderer::
523531
prepare(const std::vector<std::string>& text_lines) BOOST_NOEXCEPT {
524532
const int n_lines = text_lines.size();
533+
TagTracker tag_tracker;
525534

526535
internal_lines_.resize(n_lines);
527536
line_widths_.resize(n_lines);
528537
line_positions_.resize(n_lines);
529538
for (int i = 0; i < n_lines; ++i) {
530-
internal_lines_[i] = get_internal_chars(text_lines[i]);
539+
internal_lines_[i] = get_internal_chars(text_lines[i], tag_tracker);
531540
prepare_glyphs(internal_lines_[i]);
532541
line_widths_[i] = get_text_width(internal_lines_[i]);
533542
line_positions_[i].second = margin_bottom_ + (n_lines-i-1)*line_height_;
@@ -562,14 +571,14 @@ void SubtitleRenderer::draw() BOOST_NOEXCEPT {
562571
}
563572

564573
for (size_t i = 0; i < n_lines; ++i) {
565-
draw_text(vg_font_border_, vg_font_italic_border_,
574+
draw_text(vg_font_border_,
566575
internal_lines_[i],
567576
line_positions_[i].first, line_positions_[i].second,
568577
0);
569578
}
570579

571580
for (size_t i = 0; i < n_lines; ++i) {
572-
draw_text(vg_font_, vg_font_italic_,
581+
draw_text(vg_font_,
573582
internal_lines_[i],
574583
line_positions_[i].first, line_positions_[i].second,
575584
white_level_);

0 commit comments

Comments
 (0)