Skip to content

Commit 96f7398

Browse files
authored
avoid horizontal overlapping background for opaque subs (#3334)
1 parent 182153b commit 96f7398

File tree

2 files changed

+166
-2
lines changed

2 files changed

+166
-2
lines changed

src/Subtitles/RTS.cpp

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,28 @@ CWord::CWord(const STSStyle& style, CStringW str, int ktype, int kstart, int ken
129129

130130
}
131131

132+
133+
CWord::CWord(RenderingCaches& renderingCaches)
134+
: m_fDrawn(false)
135+
, m_p(INT_MAX, INT_MAX)
136+
, m_renderingCaches(renderingCaches)
137+
, m_scalex(0)
138+
, m_scaley(0)
139+
, m_str(L"")
140+
, m_fWhiteSpaceChar(false)
141+
, m_fLineBreak(false)
142+
, m_style()
143+
, m_pOpaqueBox(nullptr)
144+
, m_ktype(0)
145+
, m_kstart(0)
146+
, m_kend(0)
147+
, m_width(0)
148+
, m_ascent(0)
149+
, m_descent(0)
150+
{
151+
}
152+
153+
132154
CWord::~CWord()
133155
{
134156
delete m_pOpaqueBox;
@@ -603,6 +625,12 @@ CText::CText(const STSStyle& style, CStringW str, int ktype, int kstart, int ken
603625
m_width = (int)(m_style.fontScaleX / 100 * m_width + 4) >> 3;
604626
}
605627

628+
//null constructor for use by CLineBG
629+
CText::CText(RenderingCaches& renderingCaches)
630+
:CWord(renderingCaches)
631+
, m_RTS(nullptr) {
632+
}
633+
606634
CWord* CText::Copy()
607635
{
608636
return DEBUG_NEW CText(*this);
@@ -747,6 +775,118 @@ bool CText::CreatePath()
747775
return true;
748776
}
749777

778+
779+
CLineBG::CLineBG(RenderingCaches& renderingCaches)
780+
: CText(renderingCaches) {
781+
}
782+
783+
std::shared_ptr<CLineBG> CLineBG::CLineBGFactory(CLine const* line, RenderingCaches& renderingCaches) {
784+
if (!line || line->GetCount() < 2) { //single word does not have need of a combining algorithm
785+
return nullptr;
786+
}
787+
788+
789+
std::shared_ptr<CLineBG> lineBG = std::make_shared<CLineBG>(renderingCaches);
790+
791+
bool first = true;
792+
POSITION pos = line->GetHeadPosition();
793+
while (pos) {
794+
CWord* w = line->GetNext(pos);
795+
if (first) {
796+
if (w->m_style.borderStyle == 0) {
797+
return nullptr;
798+
}
799+
800+
lineBG->m_scalex = w->m_scalex;
801+
lineBG->m_scaley = w->m_scaley;
802+
lineBG->m_str = w->m_str;
803+
lineBG->m_style = w->m_style;
804+
lineBG->m_ktype = w->m_ktype;
805+
lineBG->m_kstart = w->m_kstart;
806+
lineBG->m_kend = w->m_kend;
807+
lineBG->m_width = w->m_width;
808+
lineBG->m_ascent = w->m_ascent;
809+
lineBG->m_descent = w->m_descent;
810+
first = false;
811+
} else if (lineBG->m_scalex != w->m_scalex ||
812+
lineBG->m_scaley != w->m_scaley ||
813+
lineBG->m_ktype != w->m_ktype ||
814+
lineBG->m_kstart != w->m_kstart ||
815+
lineBG->m_kend != w->m_kend ||
816+
lineBG->m_ascent != w->m_ascent ||
817+
lineBG->m_descent != w->m_descent) {
818+
return nullptr; //to combine words into one line, we currently restrict it to words who have identical properties
819+
} else {
820+
//check style
821+
STSStyle s1(lineBG->m_style);
822+
STSStyle s2(w->m_style);
823+
//everything in style must match except these properties
824+
s2.fontWeight = s1.fontWeight;
825+
s2.fItalic = s1.fItalic;
826+
s2.fUnderline = s1.fUnderline;
827+
s2.fStrikeOut = s1.fStrikeOut;
828+
829+
if (s2 != s1) {
830+
return nullptr;
831+
}
832+
lineBG->m_width += w->m_width;
833+
}
834+
}
835+
return lineBG;
836+
}
837+
838+
//see CLine::PaintShadow
839+
CRect CLineBG::PaintLineShadow(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPoint p, CPoint org, int time, int alpha) {
840+
CRect bbox(0, 0, 0, 0);
841+
842+
if (m_style.shadowDepthX != 0 || m_style.shadowDepthY != 0) {
843+
int x = p.x + (int)(m_style.shadowDepthX + 0.5);
844+
int y = p.y + m_ascent - m_ascent + (int)(m_style.shadowDepthY + 0.5);
845+
846+
DWORD a = 0xff - m_style.alpha[3];
847+
if (alpha > 0) {
848+
a = a * (0xff - static_cast<DWORD>(alpha)) / 0xff;
849+
}
850+
COLORREF shadow = revcolor(m_style.colors[3]) | (a << 24);
851+
DWORD sw[6] = { shadow, DWORD_MAX };
852+
sw[0] = ColorConvTable::ColorCorrection(sw[0]);
853+
854+
Paint(CPoint(x, y), org);
855+
856+
if (m_style.borderStyle == 1 && m_pOpaqueBox) {
857+
bbox |= m_pOpaqueBox->Draw(spd, clipRect, pAlphaMask, x, y, sw, true, false);
858+
}
859+
}
860+
861+
return bbox;
862+
}
863+
864+
865+
//see CLine::PaintOutline
866+
CRect CLineBG::PaintLineOutline(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPoint p, CPoint org, int time, int alpha) {
867+
CRect bbox(0, 0, 0, 0);
868+
869+
bool has_outline = m_style.outlineWidthX + m_style.outlineWidthY > 0.0;
870+
if ((has_outline || m_style.borderStyle == 1) && !(m_ktype == 2 && time < m_kstart)) {
871+
int x = p.x;
872+
int y = p.y + m_ascent - m_ascent;
873+
DWORD aoutline = m_style.alpha[2];
874+
if (alpha > 0) {
875+
aoutline += alpha * (0xff - m_style.alpha[2]) / 0xff;
876+
}
877+
COLORREF outline = revcolor(has_outline ? m_style.colors[2] : m_style.colors[3]) | ((0xff - aoutline) << 24);
878+
DWORD sw[6] = { outline, DWORD_MAX };
879+
sw[0] = ColorConvTable::ColorCorrection(sw[0]);
880+
881+
Paint(CPoint(x, y), org);
882+
if (m_style.borderStyle == 1 && m_pOpaqueBox) {
883+
bbox |= m_pOpaqueBox->Draw(spd, clipRect, pAlphaMask, x, y, sw, true, false);
884+
}
885+
}
886+
887+
return bbox;
888+
}
889+
750890
// CPolygon
751891

752892
CPolygon::CPolygon(const STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley, int baseline,
@@ -1255,6 +1395,7 @@ void CLine::Compact()
12551395
}
12561396
}
12571397

1398+
//note that CLineBG::PaintLineShadow is derived from this code and should be updated if this is changed
12581399
CRect CLine::PaintShadow(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPoint p, CPoint org, int time, int alpha)
12591400
{
12601401
CRect bbox(0, 0, 0, 0);
@@ -1296,6 +1437,7 @@ CRect CLine::PaintShadow(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPo
12961437
return bbox;
12971438
}
12981439

1440+
//note that CLineBG::PaintLineOutline is derived from this code and should be updated if this is changed
12991441
CRect CLine::PaintOutline(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPoint p, CPoint org, int time, int alpha)
13001442
{
13011443
CRect bbox(0, 0, 0, 0);
@@ -3554,8 +3696,14 @@ STDMETHODIMP CRenderedTextSubtitle::Render(SubPicDesc& spd, REFERENCE_TIME rt, d
35543696
}
35553697
} else {
35563698
if (paintBG) {
3557-
bbox2 |= l->PaintShadow(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
3558-
bbox2 |= l->PaintOutline(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
3699+
auto lineBG = CLineBG::CLineBGFactory(l, m_renderingCaches);
3700+
if (lineBG) {
3701+
bbox2 |= lineBG->PaintLineShadow(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
3702+
bbox2 |= lineBG->PaintLineOutline(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
3703+
} else {
3704+
bbox2 |= l->PaintShadow(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
3705+
bbox2 |= l->PaintOutline(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
3706+
}
35593707
}
35603708
if (paintBody) {
35613709
bbox2 |= l->PaintBody(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);

src/Subtitles/RTS.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,12 @@ struct CTextDims {
123123
};
124124

125125
class CPolygon;
126+
class CLineBG;
126127

127128
class CWord : public Rasterizer
128129
{
130+
friend class CLineBG;
131+
129132
bool m_fDrawn;
130133
CPoint m_p;
131134

@@ -159,6 +162,7 @@ class CWord : public Rasterizer
159162
// str[0] = 0 -> m_fLineBreak = true (in this case we only need and use the height of m_font from the whole class)
160163
CWord(const STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley,
161164
RenderingCaches& renderingCaches);
165+
CWord(RenderingCaches& renderingCaches);
162166
virtual ~CWord();
163167

164168
virtual CWord* Copy() = 0;
@@ -178,12 +182,24 @@ class CText : public CWord
178182
public:
179183
CText(const STSStyle& style, CStringW str, int ktype, int kstart, int kend, double scalex, double scaley,
180184
RenderingCaches& renderingCaches);
185+
CText(RenderingCaches& renderingCaches);
181186

182187
virtual CWord* Copy();
183188
virtual bool Append(CWord* w);
184189
void SetRts(CRenderedTextSubtitle* RTS) { m_RTS = RTS; };
185190
};
186191

192+
class CLine;
193+
class CLineBG : public CText
194+
{
195+
public:
196+
CLineBG(RenderingCaches& renderingCaches);
197+
static std::shared_ptr<CLineBG> CLineBGFactory(CLine const* line, RenderingCaches& renderingCaches);
198+
CRect PaintLineShadow(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPoint p, CPoint org, int time, int alpha);
199+
CRect PaintLineOutline(SubPicDesc& spd, CRect& clipRect, BYTE* pAlphaMask, CPoint p, CPoint org, int time, int alpha);
200+
virtual CLineBG* Copy() { return nullptr; }; //not used
201+
};
202+
187203
class CPolygon : public CWord
188204
{
189205
bool GetPOINT(LPCWSTR& str, POINT& point) const;

0 commit comments

Comments
 (0)