1919#include < QtGui/QTextDocument>
2020#include < QtGui/QTextFrame>
2121#include < QRegularExpression>
22+ #include < QHash>
2223
2324#include " script.h"
2425#include " subtitlestyle.h"
@@ -46,11 +47,13 @@ SubtitleStyle::SubtitleStyle(const SubtitleStyle &p_oth, const QFont &f,
4647
4748void SubtitleStyle::setAlignment (Qt::Alignment p_alignment) {
4849 m_alignment = p_alignment;
50+ invalidateCache ();
4951}
5052
5153void SubtitleStyle::setOffsets (double p_h, double p_v) {
5254 m_offsetH = p_h;
5355 m_offsetV = p_v;
56+ invalidateCache ();
5457}
5558
5659int SubtitleStyle::marginL () const { return m_marginL; }
@@ -65,6 +68,7 @@ void SubtitleStyle::setMargins(int p_marginL, int p_marginR, int p_marginV) {
6568 m_marginL = p_marginL;
6669 m_marginR = p_marginR;
6770 m_marginV = p_marginV;
71+ invalidateCache ();
6872}
6973
7074const QString &SubtitleStyle::name () const { return m_name; }
@@ -91,16 +95,21 @@ const QFont &SubtitleStyle::font() const { return m_font; }
9195void SubtitleStyle::setFont (const QFont &f) {
9296 m_font = f;
9397 m_font.setStyleStrategy (QFont::PreferAntialias);
98+ invalidateCache ();
9499}
95100
96101const QColor &SubtitleStyle::primaryColour () const { return m_primaryColour; }
97102
98- void SubtitleStyle::setPrimaryColour (const QColor &c) { m_primaryColour = c; }
103+ void SubtitleStyle::setPrimaryColour (const QColor &c) {
104+ m_primaryColour = c;
105+ invalidateCache ();
106+ }
99107
100108qreal SubtitleStyle::lineSpacing () const { return m_lineSpacing; }
101109
102110void SubtitleStyle::setLineSpacing (qreal p_lineSpacing) {
103111 m_lineSpacing = p_lineSpacing;
112+ invalidateCache ();
104113}
105114
106115int SubtitleStyle::subtitleHeight (const Subtitle &subtitle,
@@ -135,6 +144,11 @@ const QPoint SubtitleStyle::textAnchor(const QPoint &p_point,
135144 return p_point + offset;
136145}
137146
147+ void SubtitleStyle::invalidateCache () const {
148+ qDeleteAll (m_docCache);
149+ m_docCache.clear ();
150+ }
151+
138152void SubtitleStyle::drawSubtitle (QPainter *painter, const Subtitle &subtitle,
139153 const QRect &bounds, const QPen &outline,
140154 const qreal p_scale, const qreal p_dpi) const {
@@ -152,12 +166,12 @@ void SubtitleStyle::drawSubtitle(QPainter *painter, const Subtitle &subtitle,
152166
153167 int stack = 0 ;
154168
155- foreach ( SubtitleLine line, subtitle.lines ()) {
169+ for ( const SubtitleLine & line : subtitle.lines ()) {
156170 QRect final (bounds);
157171
158172 QPoint position = line.position ();
159173
160- QString horizontalAlign = " " ;
174+ QString horizontalAlign = " center " ;
161175 if (position.x () >= 0 && position.y () >= 0 ) {
162176 // absolute positioning : (x, y)
163177 position.setX (bounds.x () + qRound (position.x () * scale.x ()));
@@ -210,28 +224,44 @@ void SubtitleStyle::drawSubtitle(QPainter *painter, const Subtitle &subtitle,
210224 stack += qRound (fontMetrics.height () * (1.0 + m_lineSpacing));
211225 }
212226
213- // Replace text and create document with the scaled font
214- QString html =
215- QString (" <style>p { font-size: 100%%; }</style><p align=\" %1\" >%2</p>" )
216- .arg (horizontalAlign)
217- .arg (line.text ());
218- QTextDocument doc;
219- // Ensure page size is at least 1x1
220- QSize pageSize (qMax (1 , final .width ()), qMax (1 , final .height ()));
221- doc.setPageSize (pageSize);
222- doc.setDefaultFont (scaledFont);
223- doc.setHtml (html);
224-
225- // Reduce document margins to 0 (all sides)
226- QTextFrame *tf = doc.rootFrame ();
227- QTextFrameFormat tff = tf->frameFormat ();
228- tff.setTopMargin (0 );
229- tff.setBottomMargin (0 );
230- tff.setLeftMargin (0 );
231- tff.setRightMargin (0 );
232- tf->setFrameFormat (tff);
233-
234- QAbstractTextDocumentLayout *layout = doc.documentLayout ();
227+ // Prepare cache key (text + font family + font point size + scale +
228+ // alignment)
229+ QString cacheKey = QString (" %1|%2|%3|%4|%5" )
230+ .arg (line.text ())
231+ .arg (scaledFont.family ())
232+ .arg (scaledFont.pointSizeF ())
233+ .arg (uniformScale)
234+ .arg (horizontalAlign);
235+
236+ QTextDocument *doc = nullptr ;
237+
238+ if (m_docCache.contains (cacheKey)) {
239+ doc = m_docCache.value (cacheKey);
240+ } else {
241+ doc = new QTextDocument ();
242+ m_docCache.insert (cacheKey, doc);
243+
244+ // Set font and HTML once
245+ doc->setDefaultFont (scaledFont);
246+ QString html = QString (" <style>p { font-size: 100%%; margin:0; "
247+ " padding:0; }</style><p align=\" %1\" >%2</p>" )
248+ .arg (horizontalAlign)
249+ .arg (line.text ());
250+ doc->setHtml (html);
251+
252+ QTextFrame *tf = doc->rootFrame ();
253+ QTextFrameFormat tff = tf->frameFormat ();
254+ tff.setTopMargin (0 );
255+ tff.setBottomMargin (0 );
256+ tff.setLeftMargin (0 );
257+ tff.setRightMargin (0 );
258+ tf->setFrameFormat (tff);
259+ }
260+
261+ // Set page size to fit final rect
262+ doc->setPageSize (QSize (qMax (1 , final .width ()), qMax (1 , final .height ())));
263+
264+ QAbstractTextDocumentLayout *layout = doc->documentLayout ();
235265 painter->setFont (scaledFont);
236266 painter->setPen (m_primaryColour);
237267 QAbstractTextDocumentLayout::PaintContext context;
@@ -241,8 +271,7 @@ void SubtitleStyle::drawSubtitle(QPainter *painter, const Subtitle &subtitle,
241271 painter->translate (final .x (), final .y ());
242272
243273 if (outline.width () > 0 ) {
244- // Paint outline by applying a text outline format to the whole document
245- QTextCursor cursor (&doc);
274+ QTextCursor cursor (doc);
246275 cursor.select (QTextCursor::Document);
247276 QTextCharFormat format;
248277 format.setTextOutline (outline);
0 commit comments