Update patch files as far as possible. Not everything is properly included.

csriapi.cpp is removed since the version a one dir up is the correct one, this one wasn't maintained.
These patch files were used as base for porting the patches to guliverkli2.

Originally committed to SVN as r2288.
This commit is contained in:
Niels Martin Hansen 2008-07-25 19:33:55 +00:00
parent b5144d09a1
commit 65990cc0eb
10 changed files with 1369 additions and 221 deletions

View file

@ -1,221 +0,0 @@
/*
* Copyright (C) 2007 Niels Martin Hansen
* http://aegisub.net/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include <afxdlgs.h>
#include <atlpath.h>
#include "resource.h"
#include "..\..\..\subtitles\VobSubFile.h"
#include "..\..\..\subtitles\RTS.h"
#include "..\..\..\subtitles\SSF.h"
#include "..\..\..\SubPic\MemSubPic.h"
// Be sure to have <csri/csri.h> in include path
#define CSRIAPI extern "C" __declspec(dllexport)
#define CSRI_OWN_HANDLES
typedef const char *csri_rend;
extern "C" struct csri_vsfilter_inst {
CRenderedTextSubtitle *rts;
CCritSec *cs;
CSize script_res;
CSize screen_res;
CRect video_rect;
enum csri_pixfmt pixfmt;
size_t readorder;
};
typedef struct csri_vsfilter_inst csri_inst;
#include <csri/csri.h>
static csri_rend csri_vsfilter = "vsfilter";
CSRIAPI csri_inst *csri_open_file(csri_rend *renderer, const char *filename, struct csri_openflag *flags)
{
int namesize;
wchar_t *namebuf;
namesize = MultiByteToWideChar(CP_UTF8, 0, filename, -1, NULL, 0);
if (!namesize)
return 0;
namesize++;
namebuf = new wchar_t[namesize];
MultiByteToWideChar(CP_UTF8, 0, filename, -1, namebuf, namesize);
csri_inst *inst = new csri_inst();
inst->cs = new CCritSec();
inst->rts = new CRenderedTextSubtitle(inst->cs);
if (inst->rts->Open(CString(namebuf), DEFAULT_CHARSET)) {
delete[] namebuf;
inst->readorder = 0;
return inst;
} else {
delete[] namebuf;
delete inst->rts;
delete inst->cs;
delete inst;
return 0;
}
}
CSRIAPI csri_inst *csri_open_mem(csri_rend *renderer, const void *data, size_t length, struct csri_openflag *flags)
{
// This is actually less effecient than opening a file, since this first writes the memory data to a temp file,
// then opens that file and parses from that.
csri_inst *inst = new csri_inst();
inst->cs = new CCritSec();
inst->rts = new CRenderedTextSubtitle(inst->cs);
if (inst->rts->Open((BYTE*)data, (int)length, DEFAULT_CHARSET, _T("CSRI memory subtitles"))) {
inst->readorder = 0;
return inst;
} else {
delete inst->rts;
delete inst->cs;
delete inst;
return 0;
}
}
CSRIAPI void csri_close(csri_inst *inst)
{
if (!inst) return;
delete inst->rts;
delete inst->cs;
delete inst;
}
CSRIAPI int csri_request_fmt(csri_inst *inst, const struct csri_fmt *fmt)
{
if (!inst) return -1;
if (!fmt->width || !fmt->height)
return -1;
// Check if pixel format is supported
switch (fmt->pixfmt) {
case CSRI_F_BGR_:
case CSRI_F_BGR:
case CSRI_F_YUY2:
case CSRI_F_YV12:
inst->pixfmt = fmt->pixfmt;
break;
default:
return -1;
}
inst->screen_res = CSize(fmt->width, fmt->height);
inst->video_rect = CRect(0, 0, fmt->width, fmt->height);
return 0;
}
CSRIAPI void csri_render(csri_inst *inst, struct csri_frame *frame, double time)
{
const double arbitrary_framerate = 25.0;
SubPicDesc spd;
spd.w = inst->screen_res.cx;
spd.h = inst->screen_res.cy;
switch (inst->pixfmt) {
case CSRI_F_BGR_:
spd.type = MSP_RGB32;
spd.bpp = 32;
spd.bits = frame->planes[0];
spd.pitch = frame->strides[0];
break;
case CSRI_F_BGR:
spd.type = MSP_RGB24;
spd.bpp = 24;
spd.bits = frame->planes[0];
spd.pitch = frame->strides[0];
break;
case CSRI_F_YUY2:
spd.type = MSP_YUY2;
spd.bpp = 16;
spd.bits = frame->planes[0];
spd.pitch = frame->strides[0];
break;
case CSRI_F_YV12:
spd.type = MSP_YV12;
spd.bpp = 12;
spd.bits = frame->planes[0];
spd.bitsU = frame->planes[1];
spd.bitsV = frame->planes[2];
spd.pitch = frame->strides[0];
spd.pitchUV = frame->strides[1];
break;
default:
// eh?
return;
}
spd.vidrect = inst->video_rect;
inst->rts->Render(spd, (REFERENCE_TIME)(time*10000000), arbitrary_framerate, inst->video_rect);
}
// No extensions supported
CSRIAPI void *csri_query_ext(csri_rend *rend, csri_ext_id extname)
{
return 0;
}
// Get info for renderer
static struct csri_info csri_vsfilter_info = {
"vsfilter_textsub", // name
"2.38-0611-3", // version (assumed version number, svn revision, patchlevel)
// 2.38-0611 is base svn 611
// 2.38-0611-1 is with clipfix and fax/fay patch
// 2.38-0611-2 adds CSRI
// 2.38-0611-3 fixes a bug in CSRI and adds fontcrash-fix and float-pos
"VSFilter/TextSub (SVN 611 + patches for clipfix, fax/fay, fontcrash-fix, float-pos and CSRI)", // longname
"Gabest", // author
"Copyright (c) 2004-2007 by Gabest and others" // copyright
};
CSRIAPI struct csri_info *csri_renderer_info(csri_rend *rend)
{
return &csri_vsfilter_info;
}
// Only one supported, obviously
CSRIAPI csri_rend *csri_renderer_byname(const char *name, const char *specific)
{
if (strcmp(name, csri_vsfilter_info.name))
return 0;
if (specific && strcmp(specific, csri_vsfilter_info.specific))
return 0;
return &csri_vsfilter;
}
// Still just one
CSRIAPI csri_rend *csri_renderer_default()
{
return &csri_vsfilter;
}
// And no further
CSRIAPI csri_rend *csri_renderer_next(csri_rend *prev)
{
return 0;
}

View file

@ -0,0 +1,331 @@
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/subtitles.vcproj
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/subtitles.vcproj (revision 2283)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/subtitles.vcproj (revision 2284)
@@ -241,6 +241,10 @@
>
</File>
<File
+ RelativePath=".\SeparableFilter.h"
+ >
+ </File>
+ <File
RelativePath=".\SSF.h"
>
</File>
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h (revision 2283)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h (revision 2284)
@@ -85,7 +85,7 @@
bool ScanConvert();
bool CreateWidenedRegion(int borderX, int borderY);
void DeleteOutlines();
- bool Rasterize(int xsub, int ysub, int fBlur);
+ bool Rasterize(int xsub, int ysub, int fBlur, double fGaussianBlur);
CRect Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int xsub, int ysub, const long* switchpts, bool fBody, bool fBorder);
};
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp (revision 2283)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp (revision 2284)
@@ -127,11 +127,11 @@
m_fDrawn = true;
- if(!Rasterize(p.x&7, p.y&7, m_style.fBlur)) return;
+ if(!Rasterize(p.x&7, p.y&7, m_style.fBlur, m_style.fGaussianBlur)) return;
}
else if((m_p.x&7) != (p.x&7) || (m_p.y&7) != (p.y&7))
{
- Rasterize(p.x&7, p.y&7, m_style.fBlur);
+ Rasterize(p.x&7, p.y&7, m_style.fBlur, m_style.fGaussianBlur);
}
m_p = p;
@@ -1421,6 +1421,8 @@
params.Add(cmd.Mid(2)), cmd = cmd.Left(2);
else if(!cmd.Find(L"a"))
params.Add(cmd.Mid(1)), cmd = cmd.Left(1);
+ else if(!cmd.Find(L"blur"))
+ params.Add(cmd.Mid(4)), cmd = cmd.Left(4);
else if(!cmd.Find(L"bord"))
params.Add(cmd.Mid(4)), cmd = cmd.Left(4);
else if(!cmd.Find(L"be"))
@@ -1536,6 +1538,13 @@
if(sub->m_scrAlignment < 0)
sub->m_scrAlignment = (n > 0 && n < 12) ? ((((n-1)&3)+1)+((n&4)?6:0)+((n&8)?3:0)) : org.scrAlignment;
}
+ else if(cmd == L"blur")
+ {
+ double n = CalcAnimation(wcstod(p, NULL), style.fGaussianBlur, fAnimate);
+ style.fGaussianBlur = !p.IsEmpty()
+ ? (n < 0 ? 0 : n)
+ : org.fGaussianBlur;
+ }
else if(cmd == L"bord")
{
double dst = wcstod(p, NULL);
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp (revision 2283)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp (revision 2284)
@@ -2907,6 +2907,7 @@
fUnderline = false;
fStrikeOut = false;
fBlur = 0;
+ fGaussianBlur = 0;
fontShiftX = fontShiftY = fontAngleZ = fontAngleX = fontAngleY = 0;
relativeTo = 2;
}
@@ -2929,6 +2930,7 @@
&& alpha[2] == s.alpha[2]
&& alpha[3] == s.alpha[3]
&& fBlur == s.fBlur
+ && fGaussianBlur == s.fGaussianBlur
&& relativeTo == s.relativeTo
&& IsFontStyleEqual(s));
}
@@ -3004,7 +3006,7 @@
s.colors[0], s.colors[1], s.colors[2], s.colors[3], s.alpha[0], s.alpha[1], s.alpha[2], s.alpha[3],
s.charSet,
s.fontName, s.fontSize, s.fontScaleX, s.fontScaleY, s.fontSpacing, s.fontWeight,
- (int)s.fItalic, (int)s.fUnderline, (int)s.fStrikeOut, s.fBlur,
+ (int)s.fItalic, (int)s.fUnderline, (int)s.fStrikeOut, s.fBlur, s.fGaussianBlur,
s.fontAngleZ, s.fontAngleX, s.fontAngleY,
s.relativeTo);
@@ -3027,7 +3029,7 @@
s.fontName = WToT(GetStr(str)); s.fontSize = GetFloat(str);
s.fontScaleX = GetFloat(str); s.fontScaleY = GetFloat(str);
s.fontSpacing = GetFloat(str); s.fontWeight = GetInt(str);
- s.fItalic = !!GetInt(str); s.fUnderline = !!GetInt(str); s.fStrikeOut = !!GetInt(str); s.fBlur = GetInt(str);
+ s.fItalic = !!GetInt(str); s.fUnderline = !!GetInt(str); s.fStrikeOut = !!GetInt(str); s.fBlur = GetInt(str); s.fGaussianBlur = GetFloat(str);
s.fontAngleZ = GetFloat(str); s.fontAngleX = GetFloat(str); s.fontAngleY = GetFloat(str);
s.relativeTo = GetInt(str);
}
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/SeparableFilter.h
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/SeparableFilter.h (revision 0)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/SeparableFilter.h (revision 2284)
@@ -0,0 +1,121 @@
+/*
+ Copyright 2007 Niels Martin Hansen
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ Contact:
+ E-mail: <jiifurusu@gmail.com>
+ IRC: jfs in #aegisub on irc.rizon.net
+
+ */
+
+#pragma once
+
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+#include <math.h>
+
+
+// Filter an image in horizontal direction with a one-dimensional filter
+// PixelWidth is the distance in bytes between pixels
+template<ptrdiff_t PixelDist>
+void SeparableFilterX(unsigned char *src, unsigned char *dst, int width, int height, ptrdiff_t stride, int *kernel, int kernel_size, int divisor)
+{
+#pragma omp parallel for
+ for (int y = 0; y < height; y++) {
+ unsigned char *in = src + y*stride;
+ unsigned char *out = dst + y*stride;
+ for (int x = 0; x < width; x++) {
+ int accum = 0;
+ for (int k = 0; k < kernel_size; k++) {
+ int xofs = k - kernel_size/2;
+ if (x+xofs < 0) xofs += width;
+ if (x+xofs >= width) xofs -= width;
+ accum += (int)(in[xofs*PixelDist] * kernel[k]);
+ }
+ accum /= divisor;
+ if (accum > 255) accum = 255;
+ if (accum < 0) accum = 0;
+ *out = (unsigned char)accum;
+ in+=PixelDist;
+ out+=PixelDist;
+ }
+ }
+}
+
+
+// Filter an image in vertical direction with a one-dimensional filter
+// This one templated with PixelWidth since the channel interlacing is horizontal only,
+// filtering once vertically will automatically catch all channels.
+// (Width must be multiplied by pixel width for that to happen though.)
+template<ptrdiff_t PixelDist>
+void SeparableFilterY(unsigned char *src, unsigned char *dst, int width, int height, ptrdiff_t stride, int *kernel, int kernel_size, int divisor)
+{
+#pragma omp parallel for
+ width *= PixelDist;
+ for (int x = 0; x < width; x+=PixelDist) {
+ unsigned char *in = src + x;
+ unsigned char *out = dst + x;
+ for (int y = 0; y < height; y++) {
+ int accum = 0;
+ for (int k = 0; k < kernel_size; k++) {
+ int yofs = k - kernel_size/2;
+ if (y+yofs < 0) yofs += height;
+ if (y+yofs >= height) yofs -= height;
+ accum += (int)(in[yofs*stride] * kernel[k]);
+ }
+ accum /= divisor;
+ if (accum > 255) accum = 255;
+ if (accum < 0) accum = 0;
+ *out = (unsigned char)accum;
+ in += stride;
+ out += stride;
+ }
+ }
+}
+
+
+static inline double NormalDist(double sigma, double x)
+{
+ if (sigma <= 0 && x == 0) return 1;
+ else if (sigma <= 0) return 0;
+ else return exp(-(x*x)/(2*sigma*sigma)) / (sigma * sqrt(2*3.1415926535));
+}
+
+
+struct GaussianKernel {
+ int *kernel;
+ int width;
+ int divisor;
+ inline GaussianKernel(double sigma)
+ {
+ width = (int)(sigma*3 + 0.5) | 1; // binary-or with 1 to make sure the number is odd
+ if (width < 3) width = 3;
+ kernel = new int[width];
+ kernel[width/2] = (int)(NormalDist(sigma, 0) * 255);
+ divisor = kernel[width/2];
+ for (int x = width/2-1; x >= 0; x--) {
+ int val = (int)(NormalDist(sigma, width/2-x) * 255 + 0.5);
+ divisor += val*2;
+ kernel[x] = val;
+ kernel[width - x - 1] = val;
+ }
+ }
+ inline ~GaussianKernel()
+ {
+ delete[] kernel;
+ }
+};
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h (revision 2283)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h (revision 2284)
@@ -50,6 +50,7 @@
bool fUnderline;
bool fStrikeOut;
int fBlur;
+ double fGaussianBlur;
double fontAngleZ, fontAngleX, fontAngleY;
double fontShiftX, fontShiftY;
int relativeTo; // 0: window, 1: video, 2: undefined (~window)
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp (revision 2283)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp (revision 2284)
@@ -25,6 +25,7 @@
#include <vector>
#include <algorithm>
#include "Rasterizer.h"
+#include "SeparableFilter.h"
Rasterizer::Rasterizer() : mpPathTypes(NULL), mpPathPoints(NULL), mPathPoints(0), mpOverlayBuffer(NULL)
{
@@ -679,7 +680,7 @@
mOutline.clear();
}
-bool Rasterizer::Rasterize(int xsub, int ysub, int fBlur)
+bool Rasterizer::Rasterize(int xsub, int ysub, int fBlur, double fGaussianBlur)
{
_TrashOverlay();
@@ -700,17 +701,25 @@
mWideBorder = (mWideBorder+7)&~7;
- if(!mWideOutline.empty() || fBlur)
+ if(!mWideOutline.empty() || fBlur || fGaussianBlur > 0)
{
+ int bluradjust = 0;
+ if (fGaussianBlur > 0)
+ mWideBorder += (int)(fGaussianBlur*3*8 + 0.5) | 1;
+ if (fBlur)
+ mWideBorder += 8;
+
+ mWideBorder = (mWideBorder+7)&~7;
+
// Expand the buffer a bit when we're blurring, since that can also widen the borders a bit
- width += 2*mWideBorder + (fBlur ? 16 : 0);
- height += 2*mWideBorder + (fBlur ? 16 : 0);
+ width += 2*mWideBorder + bluradjust*2;
+ height += 2*mWideBorder + bluradjust*2;
- xsub += mWideBorder + (fBlur ? 8 : 0);
- ysub += mWideBorder + (fBlur ? 8 : 0);
+ xsub += mWideBorder + bluradjust;
+ ysub += mWideBorder + bluradjust;
- mOffsetX -= mWideBorder + (fBlur ? 8 : 0);
- mOffsetY -= mWideBorder + (fBlur ? 8 : 0);
+ mOffsetX -= mWideBorder + bluradjust;
+ mOffsetY -= mWideBorder + bluradjust;
}
mOverlayWidth = ((width+7)>>3) + 1;
@@ -759,6 +768,28 @@
}
}
+ // Do some gaussian blur magic
+ if (fGaussianBlur > 0)
+ {
+ GaussianKernel filter(fGaussianBlur);
+ if (mOverlayWidth >= filter.width && mOverlayHeight >= filter.width)
+ {
+ int pitch = mOverlayWidth*2;
+
+ byte *tmp = new byte[pitch*mOverlayHeight];
+ if(!tmp) return(false);
+
+ int border = !mWideOutline.empty() ? 1 : 0;
+
+ byte *src = mpOverlayBuffer + border;
+
+ SeparableFilterX<2>(src, tmp, mOverlayWidth, mOverlayHeight, pitch, filter.kernel, filter.width, filter.divisor);
+ SeparableFilterY<2>(tmp, src, mOverlayWidth, mOverlayHeight, pitch, filter.kernel, filter.width, filter.divisor);
+
+ delete[] tmp;
+ }
+ }
+
// If we're blurring, do a 3x3 box blur
// Can't do it on subpictures smaller than 3x3 pixels
for (int pass = 0; pass < fBlur; pass++)
}
// For CPUID usage in Rasterizer::Draw

View file

@ -0,0 +1,106 @@
Index: subtitles/RTS.cpp
===================================================================
--- subtitles/RTS.cpp (revision 2286)
+++ subtitles/RTS.cpp (working copy)
@@ -519,7 +519,7 @@
// CClipper
-CClipper::CClipper(CStringW str, CSize size, double scalex, double scaley)
+CClipper::CClipper(CStringW str, CSize size, double scalex, double scaley, bool inverse)
: CPolygon(STSStyle(), str, 0, 0, 0, scalex, scaley, 0)
{
m_size.cx = m_size.cy = 0;
@@ -528,6 +528,7 @@
if(size.cx < 0 || size.cy < 0 || !(m_pAlphaMask = new BYTE[size.cx*size.cy])) return;
m_size = size;
+ m_inverse = inverse;
memset(m_pAlphaMask, 0, size.cx*size.cy);
@@ -556,6 +557,13 @@
src += 2*mOverlayWidth;
dst += m_size.cx;
}
+
+ if(inverse)
+ {
+ BYTE* dst = m_pAlphaMask;
+ for(int i = size.cx*size.cy; i>0; --i, ++dst)
+ *dst = 0x40 - *dst; // mask is 6 bit
+ }
}
CClipper::~CClipper()
@@ -566,7 +574,7 @@
CWord* CClipper::Copy()
{
- return(new CClipper(m_str, m_size, m_scalex, m_scaley));
+ return(new CClipper(m_str, m_size, m_scalex, m_scaley, m_inverse));
}
bool CClipper::Append(CWord* w)
@@ -969,7 +977,7 @@
{
CStringW str;
str.Format(L"m %d %d l %d %d %d %d %d %d", 0, 0, w, 0, w, h, 0, h);
- m_pClipper = new CClipper(str, size, 1, 1);
+ m_pClipper = new CClipper(str, size, 1, 1, false);
if(!m_pClipper) return;
}
@@ -1003,7 +1011,7 @@
{
CStringW str;
str.Format(L"m %d %d l %d %d %d %d %d %d", 0, 0, w, 0, w, h, 0, h);
- m_pClipper = new CClipper(str, size, 1, 1);
+ m_pClipper = new CClipper(str, size, 1, 1, false);
if(!m_pClipper) return;
}
@@ -1578,21 +1586,22 @@
}
else if(cmd == L"clip" || cmd == L"iclip")
{
+ bool invert = (cmd == L"iclip");
+
if(params.GetCount() == 1 && !sub->m_pClipper)
{
- sub->m_pClipper = new CClipper(params[0], CSize(m_size.cx>>3, m_size.cy>>3), sub->m_scalex, sub->m_scaley);
+ sub->m_pClipper = new CClipper(params[0], CSize(m_size.cx>>3, m_size.cy>>3), sub->m_scalex, sub->m_scaley, invert);
}
else if(params.GetCount() == 2 && !sub->m_pClipper)
{
int scale = max(wcstol(p, NULL, 10), 1);
- sub->m_pClipper = new CClipper(params[1], CSize(m_size.cx>>3, m_size.cy>>3), sub->m_scalex/(1<<(scale-1)), sub->m_scaley/(1<<(scale-1)));
+ sub->m_pClipper = new CClipper(params[1], CSize(m_size.cx>>3, m_size.cy>>3), sub->m_scalex/(1<<(scale-1)), sub->m_scaley/(1<<(scale-1)), invert);
}
else if(params.GetCount() == 4)
{
CRect r;
- if(cmd == L"iclip") // TODO: Also support inverse vector clips?
- sub->m_clipInverse = true;
+ sub->m_clipInverse = invert;
r.SetRect(
wcstol(params[0], NULL, 10),
Index: subtitles/RTS.h
===================================================================
--- subtitles/RTS.h (revision 2286)
+++ subtitles/RTS.h (working copy)
@@ -111,10 +111,11 @@
virtual bool Append(CWord* w);
public:
- CClipper(CStringW str, CSize size, double scalex, double scaley);
+ CClipper(CStringW str, CSize size, double scalex, double scaley, bool inverse);
virtual ~CClipper();
CSize m_size;
+ bool m_inverse;
BYTE* m_pAlphaMask;
};

View file

@ -0,0 +1,123 @@
Index: subtitles/RTS.cpp
===================================================================
--- subtitles/RTS.cpp (revision 2285)
+++ subtitles/RTS.cpp (working copy)
@@ -796,6 +796,7 @@
{
memset(m_effects, 0, sizeof(Effect*)*EF_NUMBEROFEFFECTS);
m_pClipper = NULL;
+ m_clipInverse = false;
m_scalex = m_scaley = 1;
}
@@ -1455,6 +1456,8 @@
params.Add(cmd.Mid(3)), cmd = cmd.Left(3);
else if(!cmd.Find(L"fs"))
params.Add(cmd.Mid(2)), cmd = cmd.Left(2);
+ else if(!cmd.Find(L"iclip"))
+ ;
else if(!cmd.Find(L"i"))
params.Add(cmd.Mid(1)), cmd = cmd.Left(1);
else if(!cmd.Find(L"kt") || !cmd.Find(L"kf") || !cmd.Find(L"ko"))
@@ -1573,7 +1576,7 @@
? (n == 0 ? FW_NORMAL : n == 1 ? FW_BOLD : n >= 100 ? n : org.fontWeight)
: org.fontWeight;
}
- else if(cmd == L"clip")
+ else if(cmd == L"clip" || cmd == L"iclip")
{
if(params.GetCount() == 1 && !sub->m_pClipper)
{
@@ -1588,6 +1591,9 @@
{
CRect r;
+ if(cmd == L"iclip") // TODO: Also support inverse vector clips?
+ sub->m_clipInverse = true;
+
r.SetRect(
wcstol(params[0], NULL, 10),
wcstol(params[1], NULL, 10),
@@ -2458,6 +2464,13 @@
p = p2;
+ // Rectangles for inverse clip
+ CRect iclipRect[4];
+ iclipRect[0] = CRect(0, 0, spd.w, clipRect.top);
+ iclipRect[1] = CRect(0, clipRect.top, clipRect.left, clipRect.bottom);
+ iclipRect[2] = CRect(clipRect.right, clipRect.top, spd.w, clipRect.bottom);
+ iclipRect[3] = CRect(0, clipRect.bottom, spd.w, spd.h);
+
pos = s->GetHeadPosition();
while(pos)
{
@@ -2467,7 +2480,17 @@
: (s->m_scrAlignment%3) == 0 ? org.x - l->m_width
: org.x - (l->m_width/2);
- bbox2 |= l->PaintShadow(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
+ if (s->m_clipInverse)
+ {
+ bbox2 |= l->PaintShadow(spd, iclipRect[0], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintShadow(spd, iclipRect[1], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintShadow(spd, iclipRect[2], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintShadow(spd, iclipRect[3], pAlphaMask, p, org2, m_time, alpha);
+ }
+ else
+ {
+ bbox2 |= l->PaintShadow(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
+ }
p.y += l->m_ascent + l->m_descent;
}
@@ -2483,7 +2506,17 @@
: (s->m_scrAlignment%3) == 0 ? org.x - l->m_width
: org.x - (l->m_width/2);
- bbox2 |= l->PaintOutline(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
+ if (s->m_clipInverse)
+ {
+ bbox2 |= l->PaintOutline(spd, iclipRect[0], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintOutline(spd, iclipRect[1], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintOutline(spd, iclipRect[2], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintOutline(spd, iclipRect[3], pAlphaMask, p, org2, m_time, alpha);
+ }
+ else
+ {
+ bbox2 |= l->PaintOutline(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
+ }
p.y += l->m_ascent + l->m_descent;
}
@@ -2499,7 +2532,17 @@
: (s->m_scrAlignment%3) == 0 ? org.x - l->m_width
: org.x - (l->m_width/2);
- bbox2 |= l->PaintBody(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
+ if (s->m_clipInverse)
+ {
+ bbox2 |= l->PaintBody(spd, iclipRect[0], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintBody(spd, iclipRect[1], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintBody(spd, iclipRect[2], pAlphaMask, p, org2, m_time, alpha);
+ bbox2 |= l->PaintBody(spd, iclipRect[3], pAlphaMask, p, org2, m_time, alpha);
+ }
+ else
+ {
+ bbox2 |= l->PaintBody(spd, clipRect, pAlphaMask, p, org2, m_time, alpha);
+ }
p.y += l->m_ascent + l->m_descent;
}
Index: subtitles/RTS.h
===================================================================
--- subtitles/RTS.h (revision 2279)
+++ subtitles/RTS.h (working copy)
@@ -172,6 +172,7 @@
CRect m_rect, m_clip;
int m_topborder, m_bottomborder;
+ bool m_clipInverse;
double m_scalex, m_scaley;

View file

@ -0,0 +1,12 @@
Index: RTS.cpp
===================================================================
--- RTS.cpp (revision 1535)
+++ RTS.cpp (revision 1536)
@@ -2283,6 +2283,7 @@
if(t1 <= 0 && t2 <= 0) {t1 = 0; t2 = m_delay;}
if(m_time <= t1) p = p1;
+ else if (p1 == p2) p = p1; // jfs: avoid rounding error problems sometimes causing subtitles with \pos to jump around a bit
else if(t1 < m_time && m_time < t2)
{
double t = 1.0*(m_time-t1)/(t2-t1);

View file

@ -0,0 +1,18 @@
Index: RTS.cpp
===================================================================
--- RTS.cpp (revision 2275)
+++ RTS.cpp (revision 2276)
@@ -702,11 +702,11 @@
if(w->m_style.borderStyle == 0)
{
- bbox |= w->Draw(spd, clipRect, pAlphaMask, x, y, sw, !w->m_style.alpha[0] && !w->m_style.alpha[1], true);
+ bbox |= w->Draw(spd, clipRect, pAlphaMask, x, y, sw, false, true);
}
else if(w->m_style.borderStyle == 1 && w->m_pOpaqueBox)
{
- bbox |= w->m_pOpaqueBox->Draw(spd, clipRect, pAlphaMask, x, y, sw, true/*!w->m_style.alpha[0] && !w->m_style.alpha[1]*/, false);
+ bbox |= w->m_pOpaqueBox->Draw(spd, clipRect, pAlphaMask, x, y, sw, true, false);
}
}

View file

@ -0,0 +1,15 @@
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp (revision 2284)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp (revision 2285)
@@ -703,7 +703,9 @@
if(w->m_style.borderStyle == 0)
{
- bbox |= w->Draw(spd, clipRect, pAlphaMask, x, y, sw, false, true);
+ // Always draw border part of widened region
+ // Draw fill part of widened region only if there isn't a chance the real fill is transculent
+ bbox |= w->Draw(spd, clipRect, pAlphaMask, x, y, sw, !(w->m_style.alpha[0]||w->m_style.alpha[1]||alpha), true);
}
else if(w->m_style.borderStyle == 1 && w->m_pOpaqueBox)
{

View file

@ -0,0 +1,174 @@
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h (revision 2278)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h (revision 2279)
@@ -85,7 +85,7 @@
bool ScanConvert();
bool CreateWidenedRegion(int borderX, int borderY);
void DeleteOutlines();
- bool Rasterize(int xsub, int ysub, bool fBlur);
+ bool Rasterize(int xsub, int ysub, int fBlur);
CRect Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int xsub, int ysub, const long* switchpts, bool fBody, bool fBorder);
};
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp (revision 2278)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp (revision 2279)
@@ -1550,9 +1550,9 @@
}
else if(cmd == L"be")
{
- int n = wcstol(p, NULL, 10);
+ int n = (int)(CalcAnimation(wcstol(p, NULL, 10), style.fBlur, fAnimate)+0.5);
style.fBlur = !p.IsEmpty()
- ? (n == 0 ? false : n == 1 ? true : org.fBlur)
+ ? n
: org.fBlur;
}
else if(cmd == L"b")
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp (revision 2278)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp (revision 2279)
@@ -1578,7 +1578,7 @@
style->fItalic = !!GetInt(buff);
style->fUnderline = !!GetInt(buff);
style->fStrikeOut = !!GetInt(buff);
- style->fBlur = !!GetInt(buff);
+ style->fBlur = GetInt(buff) ? 1 : 0;
style->fontScaleX = GetFloat(buff);
style->fontScaleY = GetFloat(buff);
style->fontSpacing = GetFloat(buff);
@@ -2906,7 +2906,7 @@
fItalic = false;
fUnderline = false;
fStrikeOut = false;
- fBlur = false;
+ fBlur = 0;
fontShiftX = fontShiftY = fontAngleZ = fontAngleX = fontAngleY = 0;
relativeTo = 2;
}
@@ -3004,7 +3004,7 @@
s.colors[0], s.colors[1], s.colors[2], s.colors[3], s.alpha[0], s.alpha[1], s.alpha[2], s.alpha[3],
s.charSet,
s.fontName, s.fontSize, s.fontScaleX, s.fontScaleY, s.fontSpacing, s.fontWeight,
- (int)s.fItalic, (int)s.fUnderline, (int)s.fStrikeOut, (int)s.fBlur,
+ (int)s.fItalic, (int)s.fUnderline, (int)s.fStrikeOut, s.fBlur,
s.fontAngleZ, s.fontAngleX, s.fontAngleY,
s.relativeTo);
@@ -3027,7 +3027,7 @@
s.fontName = WToT(GetStr(str)); s.fontSize = GetFloat(str);
s.fontScaleX = GetFloat(str); s.fontScaleY = GetFloat(str);
s.fontSpacing = GetFloat(str); s.fontWeight = GetInt(str);
- s.fItalic = !!GetInt(str); s.fUnderline = !!GetInt(str); s.fStrikeOut = !!GetInt(str); s.fBlur = !!GetInt(str);
+ s.fItalic = !!GetInt(str); s.fUnderline = !!GetInt(str); s.fStrikeOut = !!GetInt(str); s.fBlur = GetInt(str);
s.fontAngleZ = GetFloat(str); s.fontAngleX = GetFloat(str); s.fontAngleY = GetFloat(str);
s.relativeTo = GetInt(str);
}
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h (revision 2278)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h (revision 2279)
@@ -49,7 +49,7 @@
bool fItalic;
bool fUnderline;
bool fStrikeOut;
- bool fBlur;
+ int fBlur;
double fontAngleZ, fontAngleX, fontAngleY;
double fontShiftX, fontShiftY;
int relativeTo; // 0: window, 1: video, 2: undefined (~window)
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp (revision 2278)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp (revision 2279)
@@ -679,7 +679,7 @@
mOutline.clear();
}
-bool Rasterizer::Rasterize(int xsub, int ysub, bool fBlur)
+bool Rasterizer::Rasterize(int xsub, int ysub, int fBlur)
{
_TrashOverlay();
@@ -700,16 +700,17 @@
mWideBorder = (mWideBorder+7)&~7;
- if(!mWideOutline.empty())
+ if(!mWideOutline.empty() || fBlur)
{
- width += 2*mWideBorder;
- height += 2*mWideBorder;
+ // Expand the buffer a bit when we're blurring, since that can also widen the borders a bit
+ width += 2*mWideBorder + (fBlur ? 16 : 0);
+ height += 2*mWideBorder + (fBlur ? 16 : 0);
- xsub += mWideBorder;
- ysub += mWideBorder;
+ xsub += mWideBorder + (fBlur ? 8 : 0);
+ ysub += mWideBorder + (fBlur ? 8 : 0);
- mOffsetX -= mWideBorder;
- mOffsetY -= mWideBorder;
+ mOffsetX -= mWideBorder + (fBlur ? 8 : 0);
+ mOffsetY -= mWideBorder + (fBlur ? 8 : 0);
}
mOverlayWidth = ((width+7)>>3) + 1;
@@ -760,32 +761,35 @@
// If we're blurring, do a 3x3 box blur
// Can't do it on subpictures smaller than 3x3 pixels
- if(fBlur && mOverlayWidth >= 3 && mOverlayHeight >= 3)
+ for (int pass = 0; pass < fBlur; pass++)
{
- int pitch = mOverlayWidth*2;
+ if(mOverlayWidth >= 3 && mOverlayHeight >= 3)
+ {
+ int pitch = mOverlayWidth*2;
- byte* tmp = new byte[pitch*mOverlayHeight];
- if(!tmp) return(false);
+ byte* tmp = new byte[pitch*mOverlayHeight];
+ if(!tmp) return(false);
- memcpy(tmp, mpOverlayBuffer, pitch*mOverlayHeight);
+ memcpy(tmp, mpOverlayBuffer, pitch*mOverlayHeight);
- int border = !mWideOutline.empty() ? 1 : 0;
+ int border = !mWideOutline.empty() ? 1 : 0;
- // This could be done in a separated way and win some speed
- for(int j = 1; j < mOverlayHeight-1; j++)
- {
- byte* src = tmp + pitch*j + 2 + border;
- byte* dst = mpOverlayBuffer + pitch*j + 2 + border;
+ // This could be done in a separated way and win some speed
+ for(int j = 1; j < mOverlayHeight-1; j++)
+ {
+ byte* src = tmp + pitch*j + 2 + border;
+ byte* dst = mpOverlayBuffer + pitch*j + 2 + border;
- for(int i = 1; i < mOverlayWidth-1; i++, src+=2, dst+=2)
- {
- *dst = (src[-2-pitch] + (src[-pitch]<<1) + src[+2-pitch]
- + (src[-2]<<1) + (src[0]<<2) + (src[+2]<<1)
- + src[-2+pitch] + (src[+pitch]<<1) + src[+2+pitch]) >> 4;
+ for(int i = 1; i < mOverlayWidth-1; i++, src+=2, dst+=2)
+ {
+ *dst = (src[-2-pitch] + (src[-pitch]<<1) + src[+2-pitch]
+ + (src[-2]<<1) + (src[0]<<2) + (src[+2]<<1)
+ + src[-2+pitch] + (src[+pitch]<<1) + src[+2+pitch]) >> 4;
+ }
}
+
+ delete [] tmp;
}
-
- delete [] tmp;
}
return true;

View file

@ -0,0 +1,42 @@
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp (revision 2281)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp (revision 2282)
@@ -344,6 +344,7 @@
mOutline.clear();
mWideOutline.clear();
+ mWideBorder = 0;
// Determine bounding box
@@ -649,7 +650,9 @@
if(rx < 0) rx = 0;
if(ry < 0) ry = 0;
- if (ry > 0 && rx > 0)
+ mWideBorder = max(rx,ry);
+
+ if (ry > 0)
{
// Do a half circle.
// _OverlapRegion mirrors this so both halves are done.
@@ -657,8 +660,7 @@
{
int x = (int)(0.5 + sqrt(float(ry*ry - y*y)) * float(rx)/float(ry));
- // If x=0 nothing will be drawn for this overlap, not sure why
- _OverlapRegion(mWideOutline, mOutline, max(x,1), y);
+ _OverlapRegion(mWideOutline, mOutline, x, y);
}
}
else if (ry == 0 && rx > 0)
@@ -668,8 +670,6 @@
_OverlapRegion(mWideOutline, mOutline, rx, 0);
}
- mWideBorder = max(rx,ry);
-
return true;
}

View file

@ -0,0 +1,548 @@
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/StyleEditorDialog.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/StyleEditorDialog.cpp (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/StyleEditorDialog.cpp (revision 2278)
@@ -115,8 +115,8 @@
m_stss.fontScaleY = m_scaley;
m_stss.borderStyle = m_borderstyle;
- m_stss.outlineWidth = m_borderwidth;
- m_stss.shadowDepth = m_shadowdepth;
+ m_stss.outlineWidthX = m_stss.outlineWidthY = m_borderwidth;
+ m_stss.shadowDepthX = m_stss.shadowDepthY = m_shadowdepth;
m_stss.scrAlignment = m_screenalignment+1;
m_stss.marginRect = m_margin;
@@ -147,9 +147,9 @@
m_scaleyspin.SetRange32(-10000, 10000);
m_borderstyle = m_stss.borderStyle;
- m_borderwidth = m_stss.outlineWidth;
+ m_borderwidth = min(m_stss.outlineWidthX, m_stss.outlineWidthY);
m_borderwidthspin.SetRange32(0, 10000);
- m_shadowdepth = m_stss.shadowDepth;
+ m_shadowdepth = min(m_stss.shadowDepthX, m_stss.shadowDepthY);
m_shadowdepthspin.SetRange32(0, 10000);
m_screenalignment = m_stss.scrAlignment-1;
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/DirectVobSub.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/DirectVobSub.cpp (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/DirectVobSub.cpp (revision 2278)
@@ -246,8 +246,8 @@
}
if(color) *color = m_defStyle.colors[0];
- if(fShadow) *fShadow = m_defStyle.shadowDepth>0;
- if(fOutline) *fOutline = m_defStyle.outlineWidth>0;
+ if(fShadow) *fShadow = (m_defStyle.shadowDepthX+m_defStyle.shadowDepthY)>0;
+ if(fOutline) *fOutline = (m_defStyle.outlineWidthX+m_defStyle.outlineWidthY)>0;
if(fAdvancedRenderer) *fAdvancedRenderer = m_fAdvancedRenderer;
return S_OK;
@@ -283,8 +283,8 @@
}
m_defStyle.colors[0] = color;
- m_defStyle.shadowDepth = fShadow?2:0;
- m_defStyle.outlineWidth = fOutline?2:0;
+ m_defStyle.shadowDepthX = m_defStyle.shadowDepthY = fShadow?2:0;
+ m_defStyle.outlineWidthX = m_defStyle.outlineWidthY = fOutline?2:0;
return S_OK;
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.h (revision 2278)
@@ -83,7 +83,7 @@
bool PartialBeginPath(HDC hdc, bool bClearPath);
bool PartialEndPath(HDC hdc, long dx, long dy);
bool ScanConvert();
- bool CreateWidenedRegion(int border);
+ bool CreateWidenedRegion(int borderX, int borderY);
void DeleteOutlines();
bool Rasterize(int xsub, int ysub, bool fBlur);
CRect Draw(SubPicDesc& spd, CRect& clipRect, byte* pAlphaMask, int xsub, int ysub, const long* switchpts, bool fBody, bool fBorder);
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.cpp (revision 2278)
@@ -116,9 +116,9 @@
if(!ScanConvert()) return;
- if(m_style.borderStyle == 0 && m_style.outlineWidth > 0)
+ if(m_style.borderStyle == 0 && (m_style.outlineWidthX+m_style.outlineWidthY > 0))
{
- if(!CreateWidenedRegion((int)(m_style.outlineWidth+0.5))) return;
+ if(!CreateWidenedRegion((int)(m_style.outlineWidthX+0.5), (int)(m_style.outlineWidthY+0.5))) return;
}
else if(m_style.borderStyle == 1)
{
@@ -188,18 +188,19 @@
STSStyle style = m_style;
style.borderStyle = 0;
- style.outlineWidth = 0;
+ style.outlineWidthX = style.outlineWidthY = 0;
style.colors[0] = m_style.colors[2];
style.alpha[0] = m_style.alpha[2];
- int w = (int)(m_style.outlineWidth + 0.5);
+ int w = (int)(m_style.outlineWidthX + 0.5);
+ int h = (int)(m_style.outlineWidthY + 0.5);
CStringW str;
str.Format(L"m %d %d l %d %d %d %d %d %d",
- -w, -w,
- m_width+w, -w,
- m_width+w, m_ascent+m_descent+w,
- -w, m_ascent+m_descent+w);
+ -w, -h,
+ m_width+w, -h,
+ m_width+w, m_ascent+m_descent+h,
+ -w, m_ascent+m_descent+h);
m_pOpaqueBox = new CPolygon(style, str, 0, 0, 0, 1.0/8, 1.0/8, 0);
@@ -622,7 +623,7 @@
AddTail(last = w->Copy());
}
- m_ascent = m_descent = m_border = 0;
+ m_ascent = m_descent = m_borderX = m_borderY = 0;
pos = GetHeadPosition();
while(pos)
@@ -631,7 +632,8 @@
if(m_ascent < w->m_ascent) m_ascent = w->m_ascent;
if(m_descent < w->m_descent) m_descent = w->m_descent;
- if(m_border < w->m_style.outlineWidth) m_border = (int)(w->m_style.outlineWidth+0.5);
+ if(m_borderX < w->m_style.outlineWidthX) m_borderX = (int)(w->m_style.outlineWidthX+0.5);
+ if(m_borderY < w->m_style.outlineWidthY) m_borderY = (int)(w->m_style.outlineWidthY+0.5);
}
}
@@ -646,10 +648,10 @@
if(w->m_fLineBreak) return(bbox); // should not happen since this class is just a line of text without any breaks
- if(w->m_style.shadowDepth > 0)
+ if(w->m_style.shadowDepthX != 0 || w->m_style.shadowDepthY != 0)
{
- int x = p.x + (int)(w->m_style.shadowDepth+0.5);
- int y = p.y + m_ascent - w->m_ascent + (int)(w->m_style.shadowDepth+0.5);
+ int x = p.x + (int)(w->m_style.shadowDepthX+0.5);
+ int y = p.y + m_ascent - w->m_ascent + (int)(w->m_style.shadowDepthY+0.5);
DWORD a = 0xff - w->m_style.alpha[3];
if(alpha > 0) a = MulDiv(a, 0xff - alpha, 0xff);
@@ -662,7 +664,7 @@
{
bbox |= w->Draw(spd, clipRect, pAlphaMask, x, y, sw,
w->m_ktype > 0 || w->m_style.alpha[0] < 0xff,
- w->m_style.outlineWidth > 0 && !(w->m_ktype == 2 && time < w->m_kstart));
+ (w->m_style.outlineWidthX+w->m_style.outlineWidthY > 0) && !(w->m_ktype == 2 && time < w->m_kstart));
}
else if(w->m_style.borderStyle == 1 && w->m_pOpaqueBox)
{
@@ -687,8 +689,7 @@
if(w->m_fLineBreak) return(bbox); // should not happen since this class is just a line of text without any breaks
-// if((w->m_style.outlineWidth > 0 || w->m_style.borderStyle == 1 && w->m_style.outlineWidth == 0) && !(w->m_ktype == 2 && time < w->m_kstart))
- if(w->m_style.outlineWidth > 0 && !(w->m_ktype == 2 && time < w->m_kstart))
+ if(w->m_style.outlineWidthX+w->m_style.outlineWidthY > 0 && !(w->m_ktype == 2 && time < w->m_kstart))
{
int x = p.x;
int y = p.y + m_ascent - w->m_ascent;
@@ -772,7 +773,7 @@
sw[1] = 0xffffffff;
}
- sw[3] = (int)(w->m_style.outlineWidth + t*w->m_width) >> 3;
+ sw[3] = (int)(w->m_style.outlineWidthX + t*w->m_width) >> 3;
sw[4] = sw[2];
sw[5] = 0x00ffffff;
@@ -884,7 +885,7 @@
CLine* ret = new CLine();
if(!ret) return(NULL);
- ret->m_width = ret->m_ascent = ret->m_descent = ret->m_border = 0;
+ ret->m_width = ret->m_ascent = ret->m_descent = ret->m_borderX = ret->m_borderY = 0;
maxwidth = GetWrapWidth(pos, maxwidth);
@@ -896,11 +897,12 @@
if(ret->m_ascent < w->m_ascent) ret->m_ascent = w->m_ascent;
if(ret->m_descent < w->m_descent) ret->m_descent = w->m_descent;
- if(ret->m_border < w->m_style.outlineWidth) ret->m_border = (int)(w->m_style.outlineWidth+0.5);
+ if(ret->m_borderX < w->m_style.outlineWidthX) ret->m_borderX = (int)(w->m_style.outlineWidthX+0.5);
+ if(ret->m_borderY < w->m_style.outlineWidthY) ret->m_borderY = (int)(w->m_style.outlineWidthY+0.5);
if(w->m_fLineBreak)
{
- if(fEmptyLine) {ret->m_ascent /= 2; ret->m_descent /= 2; ret->m_border = 0;}
+ if(fEmptyLine) {ret->m_ascent /= 2; ret->m_descent /= 2; ret->m_borderX = ret->m_borderY = 0;}
ret->Compact();
@@ -1061,15 +1063,15 @@
l = GetNextLine(pos, size.cx - marginRect.left - marginRect.right);
if(!l) break;
- if(fFirstLine) {m_topborder = l->m_border; fFirstLine = false;}
+ if(fFirstLine) {m_topborder = l->m_borderY; fFirstLine = false;}
- spaceNeeded.cx = max(l->m_width, spaceNeeded.cx);
+ spaceNeeded.cx = max(l->m_width+l->m_borderX, spaceNeeded.cx);
spaceNeeded.cy += l->m_ascent + l->m_descent;
AddTail(l);
}
- if(l) m_bottomborder = l->m_border;
+ if(l) m_bottomborder = l->m_borderY;
m_rect = CRect(
CPoint((m_scrAlignment%3) == 1 ? marginRect.left
@@ -1477,6 +1479,14 @@
;
else if(!cmd.Find(L"u"))
params.Add(cmd.Mid(1)), cmd = cmd.Left(1);
+ else if(!cmd.Find(L"xbord"))
+ params.Add(cmd.Mid(5)), cmd = cmd.Left(5);
+ else if(!cmd.Find(L"xshad"))
+ params.Add(cmd.Mid(5)), cmd = cmd.Left(5);
+ else if(!cmd.Find(L"ybord"))
+ params.Add(cmd.Mid(5)), cmd = cmd.Left(5);
+ else if(!cmd.Find(L"yshad"))
+ params.Add(cmd.Mid(5)), cmd = cmd.Left(5);
else
nUnrecognizedTags++;
@@ -1528,10 +1538,15 @@
}
else if(cmd == L"bord")
{
- double n = CalcAnimation(wcstod(p, NULL), style.outlineWidth, fAnimate);
- style.outlineWidth = !p.IsEmpty()
- ? (n < 0 ? 0 : n)
- : org.outlineWidth;
+ double dst = wcstod(p, NULL);
+ double nx = CalcAnimation(dst, style.outlineWidthX, fAnimate);
+ style.outlineWidthX = !p.IsEmpty()
+ ? (nx < 0 ? 0 : nx)
+ : org.outlineWidthX;
+ double ny = CalcAnimation(dst, style.outlineWidthY, fAnimate);
+ style.outlineWidthY = !p.IsEmpty()
+ ? (ny < 0 ? 0 : ny)
+ : org.outlineWidthY;
}
else if(cmd == L"be")
{
@@ -1819,10 +1834,15 @@
}
else if(cmd == L"shad")
{
- double n = CalcAnimation(wcstod(p, NULL), style.shadowDepth, fAnimate);
- style.shadowDepth = !p.IsEmpty()
- ? (n < 0 ? 0 : n)
- : org.shadowDepth;
+ double dst = wcstod(p, NULL);
+ double nx = CalcAnimation(dst, style.shadowDepthX, fAnimate);
+ style.shadowDepthX = !p.IsEmpty()
+ ? (nx < 0 ? 0 : nx)
+ : org.shadowDepthX;
+ double ny = CalcAnimation(dst, style.shadowDepthY, fAnimate);
+ style.shadowDepthY = !p.IsEmpty()
+ ? (ny < 0 ? 0 : ny)
+ : org.shadowDepthY;
}
else if(cmd == L"s")
{
@@ -1872,6 +1892,38 @@
? (n == 0 ? false : n == 1 ? true : org.fUnderline)
: org.fUnderline;
}
+ else if(cmd == L"xbord")
+ {
+ double dst = wcstod(p, NULL);
+ double nx = CalcAnimation(dst, style.outlineWidthX, fAnimate);
+ style.outlineWidthX = !p.IsEmpty()
+ ? (nx < 0 ? 0 : nx)
+ : org.outlineWidthX;
+ }
+ else if(cmd == L"xshad")
+ {
+ double dst = wcstod(p, NULL);
+ double nx = CalcAnimation(dst, style.shadowDepthX, fAnimate);
+ style.shadowDepthX = !p.IsEmpty()
+ ? nx
+ : org.shadowDepthX;
+ }
+ else if(cmd == L"ybord")
+ {
+ double dst = wcstod(p, NULL);
+ double ny = CalcAnimation(dst, style.outlineWidthY, fAnimate);
+ style.outlineWidthY = !p.IsEmpty()
+ ? (ny < 0 ? 0 : ny)
+ : org.outlineWidthY;
+ }
+ else if(cmd == L"yshad")
+ {
+ double dst = wcstod(p, NULL);
+ double ny = CalcAnimation(dst, style.shadowDepthY, fAnimate);
+ style.shadowDepthY = !p.IsEmpty()
+ ? ny
+ : org.shadowDepthY;
+ }
}
// return(nUnrecognizedTags < nTags);
@@ -1949,7 +2001,7 @@
}
else if(attribs[i] == L"outline-level")
{
- style.outlineWidth = wcstol(params[i], NULL, 10);
+ style.outlineWidthX = style.outlineWidthY = wcstol(params[i], NULL, 10);
}
else if(attribs[i] == L"shadow-color")
{
@@ -1957,7 +2009,7 @@
}
else if(attribs[i] == L"shadow-level")
{
- style.shadowDepth = wcstol(params[i], NULL, 10);
+ style.shadowDepthX = style.shadowDepthY = wcstol(params[i], NULL, 10);
}
if(nColor >= 0 && nColor < 4)
@@ -2079,8 +2131,10 @@
tmp.fontSize = sub->m_scaley*tmp.fontSize*64;
tmp.fontSpacing = sub->m_scalex*tmp.fontSpacing*64;
- tmp.outlineWidth *= (m_fScaledBAS ? ((sub->m_scalex+sub->m_scaley)/2) : 1) * 8;
- tmp.shadowDepth *= (m_fScaledBAS ? ((sub->m_scalex+sub->m_scaley)/2) : 1) * 8;
+ tmp.outlineWidthX *= (m_fScaledBAS ? sub->m_scalex : 1) * 8;
+ tmp.outlineWidthY *= (m_fScaledBAS ? sub->m_scaley : 1) * 8;
+ tmp.shadowDepthX *= (m_fScaledBAS ? sub->m_scalex : 1) * 8;
+ tmp.shadowDepthY *= (m_fScaledBAS ? sub->m_scaley : 1) * 8;
if(m_nPolygon)
{
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.cpp (revision 2278)
@@ -1413,8 +1413,8 @@
if(sver >= 5) style->fontSpacing = GetFloat(buff);
if(sver >= 5) style->fontAngleZ = GetFloat(buff);
if(sver >= 4) style->borderStyle = GetInt(buff);
- style->outlineWidth = GetFloat(buff);
- style->shadowDepth = GetFloat(buff);
+ style->outlineWidthX = style->outlineWidthY = GetFloat(buff);
+ style->shadowDepthX = style->shadowDepthY = GetFloat(buff);
style->scrAlignment = GetInt(buff);
style->marginRect.left = GetInt(buff);
style->marginRect.right = GetInt(buff);
@@ -1433,8 +1433,10 @@
if(sver >= 5) style->fontSpacing = max(style->fontSpacing, 0);
style->fontAngleX = style->fontAngleY = 0;
style->borderStyle = style->borderStyle == 1 ? 0 : style->borderStyle == 3 ? 1 : 0;
- style->outlineWidth = max(style->outlineWidth, 0);
- style->shadowDepth = max(style->shadowDepth, 0);
+ style->outlineWidthX = max(style->outlineWidthX, 0);
+ style->outlineWidthY = max(style->outlineWidthY, 0);
+ style->shadowDepthX = max(style->shadowDepthX, 0);
+ style->shadowDepthY = max(style->shadowDepthY, 0);
if(sver <= 4) style->scrAlignment = (style->scrAlignment&4) ? ((style->scrAlignment&3)+6) // top
: (style->scrAlignment&8) ? ((style->scrAlignment&3)+3) // mid
: (style->scrAlignment&3); // bottom
@@ -1584,8 +1586,8 @@
style->fontAngleY = GetFloat(buff);
style->fontAngleZ = GetFloat(buff);
style->borderStyle = GetInt(buff);
- style->outlineWidth = GetFloat(buff);
- style->shadowDepth = GetFloat(buff);
+ style->outlineWidthX = style->outlineWidthY = GetFloat(buff);
+ style->shadowDepthX = style->shadowDepthY = GetFloat(buff);
style->scrAlignment = GetInt(buff);
style->marginRect.left = GetInt(buff);
style->marginRect.right = GetInt(buff);
@@ -1596,8 +1598,10 @@
style->fontScaleY = max(style->fontScaleY, 0);
style->fontSpacing = max(style->fontSpacing, 0);
style->borderStyle = style->borderStyle == 1 ? 0 : style->borderStyle == 3 ? 1 : 0;
- style->outlineWidth = max(style->outlineWidth, 0);
- style->shadowDepth = max(style->shadowDepth, 0);
+ style->outlineWidthX = max(style->outlineWidthX, 0);
+ style->outlineWidthY = max(style->outlineWidthY, 0);
+ style->shadowDepthX = max(style->shadowDepthX, 0);
+ style->shadowDepthY = max(style->shadowDepthY, 0);
ret.AddStyle(StyleName, style);
}
@@ -2707,7 +2711,7 @@
s->colors[3]&0xffffff,
s->fontWeight > FW_NORMAL ? -1 : 0, s->fItalic ? -1 : 0,
s->borderStyle == 0 ? 1 : s->borderStyle == 1 ? 3 : 0,
- (int)s->outlineWidth, (int)s->shadowDepth,
+ (int)s->outlineWidthY, (int)s->shadowDepthY,
s->scrAlignment <= 3 ? s->scrAlignment : s->scrAlignment <= 6 ? ((s->scrAlignment-3)|8) : s->scrAlignment <= 9 ? ((s->scrAlignment-6)|4) : 2,
s->marginRect.left, s->marginRect.right, (s->marginRect.top + s->marginRect.bottom) / 2,
s->alpha[0],
@@ -2728,7 +2732,7 @@
(int)s->fontScaleX, (int)s->fontScaleY,
(int)s->fontSpacing, (float)s->fontAngleZ,
s->borderStyle == 0 ? 1 : s->borderStyle == 1 ? 3 : 0,
- (int)s->outlineWidth, (int)s->shadowDepth,
+ (int)s->outlineWidthY, (int)s->shadowDepthY,
s->scrAlignment,
s->marginRect.left, s->marginRect.right, (s->marginRect.top + s->marginRect.bottom) / 2,
s->charSet);
@@ -2861,7 +2865,7 @@
(int)s->fontScaleX, (int)s->fontScaleY,
(int)s->fontSpacing, (float)s->fontAngleZ,
s->borderStyle == 0 ? 1 : s->borderStyle == 1 ? 3 : 0,
- (int)s->outlineWidth, (int)s->shadowDepth,
+ (int)s->outlineWidthY, (int)s->shadowDepthY,
s->scrAlignment,
s->marginRect.left, s->marginRect.right, (s->marginRect.top + s->marginRect.bottom) / 2,
s->charSet);
@@ -2883,8 +2887,8 @@
marginRect = CRect(20, 20, 20, 20);
scrAlignment = 2;
borderStyle = 0;
- outlineWidth = 2;
- shadowDepth = 3;
+ outlineWidthX = outlineWidthY = 2;
+ shadowDepthX = shadowDepthY = 3;
colors[0] = 0x00ffffff;
colors[1] = 0x0000ffff;
colors[2] = 0x00000000;
@@ -2912,8 +2916,10 @@
return(marginRect == s.marginRect
&& scrAlignment == s.scrAlignment
&& borderStyle == s.borderStyle
- && outlineWidth == s.outlineWidth
- && shadowDepth == s.shadowDepth
+ && outlineWidthX == s.outlineWidthX
+ && outlineWidthY == s.outlineWidthY
+ && shadowDepthX == s.shadowDepthX
+ && shadowDepthY == s.shadowDepthY
&& *((int*)&colors[0]) == *((int*)&s.colors[0])
&& *((int*)&colors[1]) == *((int*)&s.colors[1])
&& *((int*)&colors[2]) == *((int*)&s.colors[2])
@@ -2994,7 +3000,7 @@
{
style.Format(_T("%d,%d,%d,%d,%d,%d,%f,%f,0x%06x,0x%06x,0x%06x,0x%06x,0x%02x,0x%02x,0x%02x,0x%02x,%d,%s,%f,%f,%f,%f,%d,%d,%d,%d,%d,%f,%f,%f,%d"),
s.marginRect.left,s.marginRect.right,s.marginRect.top,s.marginRect.bottom,
- s.scrAlignment, s.borderStyle, s.outlineWidth, s.shadowDepth,
+ s.scrAlignment, s.borderStyle, s.outlineWidthY, s.shadowDepthY,
s.colors[0], s.colors[1], s.colors[2], s.colors[3], s.alpha[0], s.alpha[1], s.alpha[2], s.alpha[3],
s.charSet,
s.fontName, s.fontSize, s.fontScaleX, s.fontScaleY, s.fontSpacing, s.fontWeight,
@@ -3013,7 +3019,8 @@
{
CStringW str = TToW(style);
s.marginRect.left = GetInt(str); s.marginRect.right = GetInt(str); s.marginRect.top = GetInt(str); s.marginRect.bottom = GetInt(str);
- s.scrAlignment = GetInt(str); s.borderStyle = GetInt(str); s.outlineWidth = GetFloat(str); s.shadowDepth = GetFloat(str);
+ s.scrAlignment = GetInt(str); s.borderStyle = GetInt(str);
+ s.outlineWidthX = s.outlineWidthY = GetFloat(str); s.shadowDepthX = s.shadowDepthY = GetFloat(str);
for(int i = 0; i < 4; i++) s.colors[i] = (COLORREF)GetInt(str);
for(int i = 0; i < 4; i++) s.alpha[i] = GetInt(str);
s.charSet = GetInt(str);
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.h
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.h (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/RTS.h (revision 2278)
@@ -121,7 +121,7 @@
class CLine : public CAtlList<CWord*>
{
public:
- int m_width, m_ascent, m_descent, m_border;
+ int m_width, m_ascent, m_descent, m_borderX, m_borderY;
virtual ~CLine();
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/STS.h (revision 2278)
@@ -34,8 +34,10 @@
CRect marginRect; // measured from the sides
int scrAlignment; // 1 - 9: as on the numpad, 0: default
int borderStyle; // 0: outline, 1: opaque box
- double outlineWidth;
- double shadowDepth;
+ double outlineWidthX;
+ double outlineWidthY;
+ double shadowDepthX;
+ double shadowDepthY;
COLORREF colors[4]; // usually: {primary, secondary, outline/background, shadow}
BYTE alpha[4];
int charSet;
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/Rasterizer.cpp (revision 2278)
@@ -644,20 +644,31 @@
}
}
-bool Rasterizer::CreateWidenedRegion(int r)
+bool Rasterizer::CreateWidenedRegion(int rx, int ry)
{
- if(r < 0) r = 0;
+ if(rx < 0) rx = 0;
+ if(ry < 0) ry = 0;
- // Do a half circle.
- // _OverlapRegion mirrors this so both halves are done.
- for(int y = -r; y <= r; ++y)
+ if (ry > 0 && rx > 0)
{
- int x = (int)(0.5 + sqrt(float(r*r - y*y)));
+ // Do a half circle.
+ // _OverlapRegion mirrors this so both halves are done.
+ for(int y = -ry; y <= ry; ++y)
+ {
+ int x = (int)(0.5 + sqrt(float(ry*ry - y*y)) * float(rx)/float(ry));
- _OverlapRegion(mWideOutline, mOutline, x, y);
+ // If x=0 nothing will be drawn for this overlap, not sure why
+ _OverlapRegion(mWideOutline, mOutline, max(x,1), y);
+ }
}
+ else if (ry == 0 && rx > 0)
+ {
+ // There are artifacts if we don't make at least two overlaps of the line, even at same Y coord
+ _OverlapRegion(mWideOutline, mOutline, rx, 0);
+ _OverlapRegion(mWideOutline, mOutline, rx, 0);
+ }
- mWideBorder = r;
+ mWideBorder = max(rx,ry);
return true;
}
Index: C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/USFSubtitles.cpp
===================================================================
--- C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/USFSubtitles.cpp (revision 2277)
+++ C:/Users/jfs/Dev/Aegisub/vsfilter/subtitles/USFSubtitles.cpp (revision 2278)
@@ -286,8 +286,8 @@
0;
stss->borderStyle = 0;
- if(!s->fontstyle.outline.IsEmpty()) stss->outlineWidth = wcstol(s->fontstyle.outline, NULL, 10);
- if(!s->fontstyle.shadow.IsEmpty()) stss->shadowDepth = wcstol(s->fontstyle.shadow, NULL, 10);
+ if(!s->fontstyle.outline.IsEmpty()) stss->outlineWidthX = stss->outlineWidthY = wcstol(s->fontstyle.outline, NULL, 10);
+ if(!s->fontstyle.shadow.IsEmpty()) stss->shadowDepthX = stss->shadowDepthY = wcstol(s->fontstyle.shadow, NULL, 10);
for(int i = 0; i < 4; i++)
{