📄 tfont.cpp
字号:
switch ((*i)->props.alignment)
{
case 1: // SSA bottom
case 2:
case 3:
y=prefsdy-hParagraph-marginBottom;
break;
case 9: // SSA mid
case 10:
case 11:
y=(prefsdy-hParagraph)/2;
break;
case 5: // SSA top
case 6:
case 7:
y=marginTop;
break;
default:
break;
}
if (y+hParagraph>=(double)prefsdy)
y=(double)prefsdy-hParagraph-1;
if (y<0) y=0;
}
if (y+(*i)->height()>=(double)prefsdy) break;
//TODO: cleanup
int x;
unsigned int cdx=(*i)->width();
if (prefs.xpos<0) x=-prefs.xpos;
else
{
switch ((*i)->props.alignment)
{
case 1: // left(SSA)
case 5:
case 9:
x=(*i)->props.get_marginL(prefsdx);
break;
case 2: // center(SSA)
case 6:
case 10:
x=(prefsdx-cdx)/2;
if (x<0) x=0;
if (x+cdx>=prefsdx) x=prefsdx-cdx;
break;
case 3: // right(SSA)
case 7:
case 11:
x=prefsdx-cdx-(*i)->props.get_marginR(prefsdx);
break;
default: // -1 (non SSA)
x=(prefs.xpos*prefsdx)/100+prefs.posXpix;
switch (prefs.align)
{
case ALIGN_FFDSHOW:x=x-cdx/2;if (x<0) x=0;if (x+cdx>=prefsdx) x=prefsdx-cdx;break;
case ALIGN_LEFT:break;
case ALIGN_CENTER:x=x-cdx/2;break;
case ALIGN_RIGHT:x=x-cdx;break;
}
break;
}
}
// if (x+cdx>prefsdx) x=prefsdx-cdx-1;
if (x<0) x=0;
(*i)->print(x,y,prefs,prefsdx,prefsdy); // print a line (=print words).
}
}
void TrenderedSubtitleLines::add(TrenderedSubtitleLine *ln,unsigned int *height)
{
push_back(ln);
if (height)
*height+=ln->height();
}
void TrenderedSubtitleLines::clear(void)
{
for (iterator l=begin();l!=end();l++)
{
(*l)->clear();
delete *l;
}
std::vector<value_type>::clear();
}
//================================= TcharsChache =================================
TcharsChache::TcharsChache(HDC Ihdc,const short (*Imatrix)[5],const YUVcolor &Iyuv,int Ixscale,IffdshowBase *Ideci):hdc(Ihdc),matrix(Imatrix),yuv(Iyuv),xscale(Ixscale),deci(Ideci)
{
}
TcharsChache::~TcharsChache()
{
for (Tchars::iterator c=chars.begin();c!=chars.end();c++)
delete c->second;
}
template<> const TrenderedSubtitleWord* TcharsChache::getChar(const wchar_t *s,const TrenderedSubtitleLines::TprintPrefs &prefs)
{
int key=(int)*s;
Tchars::iterator l=chars.find(key);
if (l!=chars.end()) return l->second;
TrenderedSubtitleWord *ln=new TrenderedSubtitleWord(hdc,s,1,matrix,yuv,prefs,xscale);
chars[key]=ln;
return ln;
}
template<> const TrenderedSubtitleWord* TcharsChache::getChar(const char *s,const TrenderedSubtitleLines::TprintPrefs &prefs)
{
if(_mbclen((unsigned char *)s)==1)
{
int key=(int)*s;
Tchars::iterator l=chars.find(key);
if (l!=chars.end()) return l->second;
TrenderedSubtitleWord *ln=new TrenderedSubtitleWord(hdc,s,1,matrix,yuv,prefs,xscale);
chars[key]=ln;
return ln;
}
else
{
const wchar_t *mbcs=(wchar_t *)s; // ANSI-MBCS
int key=(int)*mbcs;
Tchars::iterator l=chars.find(key);
if (l!=chars.end()) return l->second;
TrenderedSubtitleWord *ln=new TrenderedSubtitleWord(hdc,s,2,matrix,yuv,prefs,xscale);
chars[key]=ln;
return ln;
}
}
//==================================== Tfont ====================================
Tfont::Tfont(IffdshowBase *Ideci):
fontManager(NULL),
deci(Ideci),
oldsub(NULL),
hdc(NULL),oldFont(NULL),
charsCache(NULL),
height(0),
fontSettings((TfontSettings*)malloc(sizeof(TfontSettings)))
{
}
Tfont::~Tfont()
{
done();
free(fontSettings);
}
void Tfont::init(const TfontSettings *IfontSettings)
{
done();
memcpy(fontSettings,IfontSettings,sizeof(TfontSettings));
hdc=CreateCompatibleDC(NULL);
if (!hdc) return;
yuvcolor=YUVcolor(fontSettings->color);
if (fontSettings->outlineStrength<100)
for (int y=-2;y<=2;y++)
for (int x=-2;x<=2;x++)
{
double d=8-(x*x+y*y);
matrix[y+2][x+2]=short(3.57*fontSettings->outlineStrength*pow(d/8,2-fontSettings->outlineRadius/50.0)+0.5);
}
if (fontSettings->fast)
charsCache=new TcharsChache(hdc,fontSettings->outlineStrength==100?NULL:matrix,yuvcolor,fontSettings->xscale,deci);
}
void Tfont::done(void)
{
lines.clear();
if (hdc)
{
if (oldFont) SelectObject(hdc,oldFont);oldFont=NULL;
DeleteDC(hdc);hdc=NULL;
}
oldsub=NULL;
if (charsCache) delete charsCache;charsCache=NULL;
}
template<class tchar> TrenderedSubtitleWord* Tfont::newWord(const tchar *s,size_t slen,TrenderedSubtitleLines::TprintPrefs prefs,const TsubtitleWord<tchar> *w,bool trimRightSpaces)
{
OUTLINETEXTMETRIC otm;
GetOutlineTextMetrics(hdc,sizeof(otm),&otm);
ffstring s1(s);
if (trimRightSpaces)
{
while (s1.size() && s1.at(s1.size()-1)==' ')
s1.erase(s1.size()-1,1);
}
if (w->props.shadowDepth != -1) // SSA/ASS/ASS2
{
if (w->props.shadowDepth == 0)
{
prefs.shadowMode = 3;
prefs.shadowSize = 0;
}
else
{
prefs.shadowMode = 2;
prefs.shadowSize = -1 * w->props.shadowDepth;
}
}
if (!w->props.isColor && fontSettings->fast && !otm.otmItalicAngle && !otm.otmTextMetrics.tmItalic && !(prefs.shadowSize!=0 && prefs.shadowMode!=3))
return new TrenderedSubtitleWord(charsCache,s1.c_str(),slen,prefs); // fast rendering
else
return new TrenderedSubtitleWord(hdc, // full rendering
s1.c_str(),
slen,
fontSettings->outlineStrength==100?NULL:matrix,w->props.isColor?w->props.color:yuvcolor,prefs,
w->props.scaleX!=-1?w->props.scaleX:fontSettings->xscale,
w->props.alignment);
}
template<class tchar> int Tfont::get_splitdx1(const TsubtitleWord<tchar> &w,int splitdx,int dx) const
{
if (w.props.get_marginR(dx) || w.props.get_marginL(dx))
return (dx- w.props.get_marginR(dx) - w.props.get_marginL(dx))*4;
else
return splitdx;
}
template<class tchar> void Tfont::prepareC(const TsubtitleTextBase<tchar> *sub,const TrenderedSubtitleLines::TprintPrefs &prefs,bool forceChange)
{
if (oldsub!=sub || forceChange)
{
oldsub=sub;
unsigned int dx,dy;
if (prefs.sizeDx && prefs.sizeDy)
{
dx=prefs.sizeDx;
dy=prefs.sizeDy;
}
else
{
dx=prefs.dx;
dy=prefs.dy;
}
lines.clear();height=0;
if (!sub) return;
if (!fontManager)
comptrQ<IffdshowDecVideo>(deci)->getFontManager(&fontManager);
bool nosplit=!fontSettings->split && !(prefs.fontchangesplit && prefs.fontsplit);
int splitdx0=nosplit?0:(prefs.textBorderLR-40>(int)dx?dx:dx-prefs.textBorderLR)*4;
for (typename TsubtitleTextBase<tchar>::const_iterator l=sub->begin();l!=sub->end();l++)
{
TrenderedSubtitleLine *line=NULL;
int splitdx=splitdx0;
int splitdx1=-1;
for (typename TsubtitleLine<tchar>::const_iterator w=l->begin();w!=l->end();w++)
{
if (splitdx1==-1)
splitdx1=get_splitdx1(*w,splitdx,dx);
LOGFONT lf;
w->props.toLOGFONT(lf,*fontSettings,dx,dy);
HFONT font=fontManager->getFont(lf);
HGDIOBJ old=SelectObject(hdc,font);
if (!oldFont) oldFont=old;
SetTextCharacterExtra(hdc,w->props.spacing>=0?w->props.spacing:fontSettings->spacing);
if (!line)
{
line=new TrenderedSubtitleLine(w->props);
splitdx1=get_splitdx1(*w,splitdx,dx);
}
if (nosplit)
line->push_back(newWord<tchar>(*w,strlen(*w),prefs,&*w));
else
{
const tchar *p=*w;
while (*p)
{
int nfit;
SIZE sz;
size_t strlenp=strlenp=strlen(p);
int *pwidths=(int*)_alloca(sizeof(int)*(strlenp+1));
if (!prefs.config->getGDI<tchar>().getTextExtentExPoint(hdc,p,(int)strlenp,splitdx1,&nfit,pwidths,&sz) || nfit>=(int)strlen(p))
{
TrenderedSubtitleWord *rw;
if (w+1==l->end())
rw=newWord(p,strlen(p),prefs,&*w,true); // trim right space
else
rw=newWord(p,strlen(p),prefs,&*w,false);
line->push_back(rw);
splitdx1-=rw->dxCharY*4;
if (splitdx1<0) splitdx1=0;
splitdx-=rw->dxCharY*4;
if (splitdx<0) splitdx=0;
break;
}
bool spaceOK=false;
if (nfit==0) nfit=1;
for (int j=nfit;j>0;j--)
if (tchar_traits<tchar>::isspace((typename tchar_traits<tchar>::uchar_t)p[j]))
{
spaceOK=true;
nfit=j;
break;
}
if (spaceOK || /* to avoid infinity loop */ splitdx1==get_splitdx1(*w,splitdx,dx))
{
TrenderedSubtitleWord *rw=newWord(p,nfit,prefs,&*w,true);
line->push_back(rw);
p+=nfit;
}
lines.add(line,&height);
line=new TrenderedSubtitleLine(w->props);
splitdx1=get_splitdx1(*w,splitdx,dx);
splitdx=splitdx0;
while (*p && tchar_traits<tchar>::isspace((typename tchar_traits<tchar>::uchar_t)*p))
p++;
}
}
}
if (line)
if (!line->empty())
lines.add(line,&height);
else
delete line;
}
}
}
template<class tchar> void Tfont::print(const TsubtitleTextBase<tchar> *sub,bool forceChange,const TrenderedSubtitleLines::TprintPrefs &prefs,unsigned int *y)
{
if (!sub) return;
prepareC(sub,prefs,forceChange);if (y) *y+=height;
lines.print(prefs);
}
template void Tfont::print(const TsubtitleTextBase<char> *sub,bool forceChange,const TrenderedSubtitleLines::TprintPrefs &prefs,unsigned int *y);
template void Tfont::print(const TsubtitleTextBase<wchar_t> *sub,bool forceChange,const TrenderedSubtitleLines::TprintPrefs &prefs,unsigned int *y);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -