subs: move rendering to text subtitles to overlay renderer
[vuplus_xbmc] / xbmc / cores / VideoRenderers / OverlayRendererGUI.cpp
1 /*
2  *  Copyright (C) 2005-2013 Team XBMC
3  *  http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "system.h"
22
23 #include "OverlayRendererGUI.h"
24 #include "settings/Settings.h"
25
26 #include "filesystem/File.h"
27 #include "Util.h"
28 #include "utils/URIUtils.h"
29 #include "utils/StringUtils.h"
30 #include "utils/log.h"
31 #include "guilib/GUITextLayout.h"
32 #include "guilib/GUIFontManager.h"
33 #include "guilib/GUIFont.h"
34 #include "cores/dvdplayer/DVDCodecs/Overlay/DVDOverlayText.h"
35 #include "cores/VideoRenderers/RenderManager.h"
36
37 using namespace OVERLAY;
38
39 static color_t color[8] = { 0xFFFFFF00
40                           , 0xFFFFFFFF
41                           , 0xFF0099FF
42                           , 0xFF00FF00
43                           , 0xFFCCFF00
44                           , 0xFF00FFFF
45                           , 0xFFE5E5E5
46                           , 0xFFC0C0C0 };
47
48 static CGUITextLayout* GetFontLayout()
49 {
50   if (CUtil::IsUsingTTFSubtitles())
51   { std::string font_file = CSettings::Get().GetString("subtitles.font");
52     std::string font_path = URIUtils::AddFileToFolder("special://home/media/Fonts/", font_file);
53     if (!XFILE::CFile::Exists(font_path))
54       font_path = URIUtils::AddFileToFolder("special://xbmc/media/Fonts/", font_file);
55
56     // We scale based on PAL4x3 - this at least ensures all sizing is constant across resolutions.
57     RESOLUTION_INFO pal(720, 576, 0);
58     CGUIFont *subtitle_font = g_fontManager.LoadTTF("__subtitle__"
59                                                     , font_path
60                                                     , color[CSettings::Get().GetInt("subtitles.color")]
61                                                     , 0
62                                                     , CSettings::Get().GetInt("subtitles.height")
63                                                     , CSettings::Get().GetInt("subtitles.style")
64                                                     , false, 1.0f, 1.0f, &pal, true);
65     CGUIFont *border_font   = g_fontManager.LoadTTF("__subtitleborder__"
66                                                     , font_path
67                                                     , 0xFF000000
68                                                     , 0
69                                                     , CSettings::Get().GetInt("subtitles.height")
70                                                     , CSettings::Get().GetInt("subtitles.style")
71                                                     , true, 1.0f, 1.0f, &pal, true);
72     if (!subtitle_font || !border_font)
73       CLog::Log(LOGERROR, "CGUIWindowFullScreen::OnMessage(WINDOW_INIT) - Unable to load subtitle font");
74     else
75       return new CGUITextLayout(subtitle_font, true, 0, border_font);
76   }
77
78   return NULL;
79 }
80
81 COverlayText::COverlayText(CDVDOverlayText * src)
82 {
83   CDVDOverlayText::CElement* e = src->m_pHead;
84   while (e)
85   {
86     if (e->IsElementType(CDVDOverlayText::ELEMENT_TYPE_TEXT))
87     {
88       CDVDOverlayText::CElementText* t = (CDVDOverlayText::CElementText*)e;
89       m_text += t->m_text;
90       m_text += "\n";
91     }
92     e = e->pNext;
93   }
94
95   // Avoid additional line breaks
96   while(StringUtils::EndsWith(m_text, "\n"))
97     m_text = StringUtils::Left(m_text, m_text.length() - 1);
98
99   // Remove HTML-like tags from the subtitles until
100   StringUtils::Replace(m_text, "\\r", "");
101   StringUtils::Replace(m_text, "\r", "");
102   StringUtils::Replace(m_text, "\\n", "[CR]");
103   StringUtils::Replace(m_text, "\n", "[CR]");
104   StringUtils::Replace(m_text, "<br>", "[CR]");
105   StringUtils::Replace(m_text, "\\N", "[CR]");
106   StringUtils::Replace(m_text, "<i>", "[I]");
107   StringUtils::Replace(m_text, "</i>", "[/I]");
108   StringUtils::Replace(m_text, "<b>", "[B]");
109   StringUtils::Replace(m_text, "</b>", "[/B]");
110   StringUtils::Replace(m_text, "<u>", "");
111   StringUtils::Replace(m_text, "<p>", "");
112   StringUtils::Replace(m_text, "<P>", "");
113   StringUtils::Replace(m_text, "&nbsp;", "");
114   StringUtils::Replace(m_text, "</u>", "");
115   StringUtils::Replace(m_text, "</i", "[/I]"); // handle tags which aren't closed properly (happens).
116   StringUtils::Replace(m_text, "</b", "[/B]");
117   StringUtils::Replace(m_text, "</u", "");
118
119   m_layout = GetFontLayout();
120
121   m_subalign = CSettings::Get().GetInt("subtitles.align");
122   if (m_subalign == SUBTITLE_ALIGN_MANUAL)
123   {
124     m_align  = ALIGN_SUBTITLE;
125     m_pos    = POSITION_RELATIVE;
126     m_x      = 0.0f;
127     m_y      = 0.0f;
128   }
129   else
130   {
131     m_align  = ALIGN_VIDEO;
132     m_pos    = POSITION_RELATIVE;
133     m_x      = 0.5f;
134     if(m_subalign == SUBTITLE_ALIGN_TOP_INSIDE
135     || m_subalign == SUBTITLE_ALIGN_TOP_OUTSIDE)
136       m_y    = 0.0f;
137     else
138       m_y    = 1.0f;
139   }
140   m_width  = 0;
141   m_height = 0;
142 }
143
144 COverlayText::~COverlayText()
145 {
146   delete m_layout;
147 }
148
149 void COverlayText::Render(OVERLAY::SRenderState &state)
150 {
151   if(m_layout == NULL)
152     return;
153
154   CRect rs, rd;
155   g_renderManager.GetVideoRect(rs, rd);
156   RESOLUTION_INFO res = g_graphicsContext.GetResInfo();
157
158   float width_max = (float) res.Overscan.right - res.Overscan.left;
159   float y, width, height;
160   m_layout->Update(m_text, width_max * 0.9f, false, true); // true to force LTR reading order (most Hebrew subs are this format)
161   m_layout->GetTextExtent(width, height);
162
163   if (m_subalign == SUBTITLE_ALIGN_MANUAL
164   ||  m_subalign == SUBTITLE_ALIGN_TOP_OUTSIDE
165   ||  m_subalign == SUBTITLE_ALIGN_BOTTOM_INSIDE)
166     y = state.y - height;
167   else
168     y = state.y;
169
170   // clamp inside screen
171   y = std::max(y, (float) res.Overscan.top);
172   y = std::min(y, res.Overscan.bottom - height);
173
174   m_layout->RenderOutline(state.x, y, 0, 0xFF000000, XBFONT_CENTER_X, width_max);
175 }