📄 tfont.cpp
字号:
{
unsigned int alpha = circle[circleSize*ry+rx];
if (alpha)
{
unsigned int dstpos = _dx*(y+ry-shadowSize)+x+rx-shadowSize;
unsigned int shadow = bmp[0][pos] * alpha >> 8;
if (msk[0][dstpos]<shadow)
msk[0][dstpos] = (unsigned char)shadow;
}
}
}
}
}
}
else if (shadowMode == 1) //Gradient classic shadow
{
unsigned int shadowStep = shadowAlpha/shadowSize;
for (unsigned int y=0; y<_dy;y++)
{
for (unsigned int x=0; x<_dx;x++)
{
unsigned int pos = _dx*y+x;
if (bmp[0][pos] == 0) continue;
/*else
bmp[0][pos] = 255;*/
unsigned int shadowAlphaGradient = shadowAlpha;
for (unsigned int xx=1; xx<=shadowSize; xx++)
{
unsigned int shadow = bmp[0][pos]*shadowAlphaGradient>>8;
if (x + xx < _dx)
{
if (y+xx < _dy &&
msk[0][_dx*(y+xx)+x+xx] <shadow)
{
msk[0][_dx*(y+xx)+x+xx] = shadow;
}
}
shadowAlphaGradient -= shadowStep;
}
}
}
}
else if (shadowMode == 2) //Classic shadow
{
shadowAlpha*=0.53;
unsigned int lookup085[256],lookupAlpha[256];
for (int i=0;i<256;i++)
{
lookup085[i]=i*0.85;
lookupAlpha[i]=i*shadowAlpha>>8;
}
for (unsigned int y=_dy-1; y>=shadowSize;y--)
{
for (unsigned int x=_dx-1; x>=shadowSize;x--)
{
unsigned int srcpos = _dx*(y-shadowSize)+x-shadowSize;
unsigned int dstpos = _dx*y+x;
unsigned char srcPixel = (unsigned char)std::max<unsigned int>(bmp[0][srcpos],lookup085[msk[0][srcpos]]); // lookup085[msk[0][srcpos]] = shadow of outline.
if (srcPixel != 0)
msk[0][dstpos] = (unsigned char)std::max<unsigned int>(msk[0][dstpos],lookupAlpha[srcPixel]);
}
}
}
}
unsigned int TrenderedSubtitleWord::getShadowSize(const TrenderedSubtitleLines::TprintPrefs &prefs,LONG fontHeight)
{
if (prefs.shadowSize==0)
return 0;
if (prefs.shadowSize < 0) // SSA/ASS/ASS2
return -1 * prefs.shadowSize;
unsigned int shadowSize = prefs.shadowSize*fontHeight/180.0+2.6;
if (prefs.shadowMode==0)
shadowSize*=0.6;
else if (prefs.shadowMode==1)
shadowSize/=1.4142; // 1.4142 = sqrt(2.0)
else if (prefs.shadowMode==2)
shadowSize*=0.4;
if (shadowSize==0)
shadowSize = 1;
if (shadowSize>16)
shadowSize = 16;
return shadowSize;
}
// fast rendering
template<class tchar> TrenderedSubtitleWord::TrenderedSubtitleWord(TcharsChache *charsChache,const tchar *s,size_t strlens,const TrenderedSubtitleLines::TprintPrefs &prefs):TrenderedSubtitleWordBase(true),shiftChroma(true)
{
const TrenderedSubtitleWord **chars=(const TrenderedSubtitleWord**)_alloca(strlens*sizeof(TrenderedSubtitleLine*));
for (int i=0;i<3;i++)
dx[i]=dy[i]=0;
for (size_t i=0;i<strlens;i++)
{
chars[i]=charsChache->getChar(&s[i],prefs);
dx[0]+=chars[i]->dxCharY;
if (s[i]=='\t')
{
int tabsize=prefs.tabsize*std::max(chars[0]->dyCharY,1U);
dx[0]=(dx[0]/tabsize+1)*tabsize;
}
for (int p=0;p<3;p++)
dy[p]=std::max(dy[p],chars[i]->dy[p]);
if(sizeof(tchar)==sizeof(char))
if(_mbclen((const unsigned char *)&s[i])==2)
i++;
}
dx[0]=(dx[0]/8+2)*8;dx[1]=dx[2]=(dx[0]/16+1)*8;
dxCharY=dx[0];
dyCharY=chars[0]->dyCharY;
for (int i=0;i<3;i++)
{
bmp[i]=(unsigned char*)aligned_calloc(dx[i],dy[i]);//bmp[1]=(unsigned char*)aligned_calloc(dxUV,dyUV);bmp[2]=(unsigned char*)aligned_calloc(dxUV,dyUV);
msk[i]=(unsigned char*)aligned_calloc(dx[i],dy[i]);//msk[1]=(unsigned char*)aligned_calloc(dxUV,dyUV);msk[2]=(unsigned char*)aligned_calloc(dxUV,dyUV);
bmpmskstride[i]=dx[i];
}
unsigned int x=0;
for (size_t i=0;i<strlens;i++)
{
if (s[i]=='\t')
{
int tabsize=prefs.tabsize*std::max(chars[0]->dyCharY,1U);
x=(x/tabsize+1)*tabsize;
}
for (unsigned int p=0;p<3;p++)
{
const unsigned char *charbmpptr=chars[i]->bmp[p],*charmskptr=chars[i]->msk[p];
unsigned char *bmpptr=bmp[p]+roundRshift(x,prefs.shiftX[p]),*mskptr=msk[p]+roundRshift(x,prefs.shiftX[p]);
for (unsigned int y=0;y<chars[i]->dy[p];y++,bmpptr+=bmpmskstride[p],mskptr+=bmpmskstride[p],charbmpptr+=chars[i]->bmpmskstride[p],charmskptr+=chars[i]->bmpmskstride[p])
{
memadd(bmpptr,charbmpptr,chars[i]->dx[p]);
memadd(mskptr,charmskptr,chars[i]->dx[p]);
}
}
x+=chars[i]->dxCharY;
if(sizeof(tchar)==sizeof(char))
if(_mbclen((const unsigned char *)&s[i])==2)
i++;
}
_mm_empty();
}
void TrenderedSubtitleWord::print(unsigned int sdx[3],unsigned char *dstLn[3],const stride_t stride[3],const unsigned char *bmp[3],const unsigned char *msk[3]) const
{
int sdx15=sdx[0]-15;
for (unsigned int y=0;y<dy[0];y++,dstLn[0]+=stride[0],msk[0]+=bmpmskstride[0],bmp[0]+=bmpmskstride[0])
{
int x=0;
for (;x<sdx15;x+=16)
{
__m64 mm0=*(__m64*)(dstLn[0]+x),mm1=*(__m64*)(dstLn[0]+x+8);
mm0=_mm_subs_pu8(mm0,*(__m64*)(msk[0]+x));mm1=_mm_subs_pu8(mm1,*(__m64*)(msk[0]+x+8));
mm0=_mm_adds_pu8(mm0,*(__m64*)(bmp[0]+x));mm1=_mm_adds_pu8(mm1,*(__m64*)(bmp[0]+x+8));
*(__m64*)(dstLn[0]+x)=mm0;*(__m64*)(dstLn[0]+x+8)=mm1;
}
for (;x<int(sdx[0]);x++)
{
int c=dstLn[0][x];
c-=msk[0][x];if (c<0) c=0;
c+=bmp[0][x];if (c>255) c=255;
dstLn[0][x]=(unsigned char)c;
}
}
__m64 m128=_mm_set1_pi8((char)128),m0=_mm_setzero_si64(),mAdd=shiftChroma?m128:m0;
int add=shiftChroma?128:0;
int sdx7=sdx[1]-7;
for (unsigned int y=0;y<dy[1];y++,dstLn[1]+=stride[1],dstLn[2]+=stride[2],msk[1]+=bmpmskstride[1],bmp[1]+=bmpmskstride[1],bmp[2]+=bmpmskstride[2])
{
int x=0;
for (;x<sdx7;x+=8)
{
__m64 mm0=*(__m64*)(dstLn[1]+x);
__m64 mm1=*(__m64*)(dstLn[2]+x);
psubb(mm0,m128);
psubb(mm1,m128);
const __m64 msk8=*(const __m64*)(msk[1]+x);
__m64 mskU=_mm_cmpgt_pi8(m0,mm0); //what to be negated
mm0=_mm_or_si64(_mm_and_si64(mskU,_mm_adds_pu8(mm0,msk8)),_mm_andnot_si64(mskU,_mm_subs_pu8(mm0,msk8)));
__m64 mskV=_mm_cmpgt_pi8(m0,mm1);
mm1=_mm_or_si64(_mm_and_si64(mskV,_mm_adds_pu8(mm1,msk8)),_mm_andnot_si64(mskV,_mm_subs_pu8(mm1,msk8)));
mm0=_mm_add_pi8(_mm_add_pi8(mm0,*(__m64*)(bmp[1]+x)),mAdd);
mm1=_mm_add_pi8(_mm_add_pi8(mm1,*(__m64*)(bmp[2]+x)),mAdd);
*(__m64*)(dstLn[1]+x)=mm0;
*(__m64*)(dstLn[2]+x)=mm1;
}
for (;x<int(sdx[1]);x++)
{
int m=msk[1][x],c;
c=dstLn[1][x];
c-=128;
if (c<0) {c+=m;if (c>0) c=0;}
else {c-=m;if (c<0) c=0;}
c+=bmp[1][x];
c+=add;
dstLn[1][x]=c;//(unsigned char)limit(c,0,255);
c=dstLn[2][x];
c-=128;
if (c<0) {c+=m;if (c>0) c=0;}
else {c-=m;if (c<0) c=0;};
c+=bmp[2][x];
c+=add;
dstLn[2][x]=c;//(unsigned char)limit(c,0,255);
}
}
/* for (int x=0;x<dx[0];x++)
for (int y=0;y<dy[0];y++)
{
if (bmp[0][dy[0]*y+x] !=0)
{
dstLn[0][x]=c
}
}*/
_mm_empty();
}
//============================== TrenderedSubtitleLine ===============================
unsigned int TrenderedSubtitleLine::width(void) const
{
unsigned int dx=0;
for (const_iterator w=begin();w!=end();w++)
dx+=(*w)->dx[0];
return dx;
}
unsigned int TrenderedSubtitleLine::height(void) const
{
unsigned int dy=0;
for (const_iterator w=begin();w!=end();w++)
dy=std::max(dy,(*w)->dy[0]);
return dy;
}
unsigned int TrenderedSubtitleLine::charHeight(void) const
{
unsigned int dy=0;
for (const_iterator w=begin();w!=end();w++)
dy=std::max(dy,(*w)->dyCharY);
return dy;
}
void TrenderedSubtitleLine::print(int startx,int starty,const TrenderedSubtitleLines::TprintPrefs &prefs,unsigned int prefsdx,unsigned int prefsdy) const
{
for (const_iterator w=begin();w!=end() && startx<(int)prefsdx;startx+=(*w)->dxCharY,w++)
{
const unsigned char *msk[3],*bmp[3];
unsigned char *dstLn[3];
int x[3];
unsigned int dx[3];
for (int i=0;i<3;i++)
{
x[i]=startx>>prefs.shiftX[i];
msk[i]=(*w)->msk[i];
bmp[i]=(*w)->bmp[i];
if (prefs.align!=ALIGN_FFDSHOW && x[i]<0)
{
msk[i]+=-x[i];
bmp[i]+=-x[i];
}
dstLn[i]=prefs.dst[i]+prefs.stride[i]*(starty>>prefs.shiftY[i]);if (x[i]>0) dstLn[i]+=x[i];
if (x[i]+(*w)->dx[i]>(prefsdx>>prefs.shiftX[i])) dx[i]=(prefsdx>>prefs.shiftX[i])-x[i];
else if (x[i]<0) dx[i]=(*w)->dx[i]+x[i];
else dx[i]=(*w)->dx[i];
dx[i]=std::min(dx[i],prefsdx>>prefs.shiftX[i]);
}
(*w)->print(dx,dstLn,prefs.stride,bmp,msk);
}
}
void TrenderedSubtitleLine::clear(void)
{
for (iterator w=begin();w!=end();w++)
delete *w;
std::vector<value_type>::clear();
}
//============================== TrenderedSubtitleLines ==============================
void TrenderedSubtitleLines::print(const TprintPrefs &prefs)
{
if (empty()) return;
unsigned int prefsdx,prefsdy;
if (prefs.sizeDx && prefs.sizeDy)
{
prefsdx=prefs.sizeDx;
prefsdy=prefs.sizeDy;
}
else
{
prefsdx=prefs.dx;
prefsdy=prefs.dy;
}
unsigned int h=0;
for (const_iterator i=begin();i!=end();i++)
h+=prefs.linespacing*(*i)->charHeight()/100;
const_reverse_iterator ri=rbegin();
unsigned int h1 = h - prefs.linespacing*(*ri)->charHeight()/100 + (*ri)->height();
double y=(prefs.ypos<0) ? -(double)prefs.ypos : ((double)prefs.ypos*prefsdy)/100-h/2;
if (y+h1 >= (double)prefsdy) y=(double)prefsdy-h1-1;
if (y<0) y=0;
int old_alignment=-1;
int old_marginTop=-1,old_marginL=-1;
for (const_iterator i=begin();i!=end();y+=(double)prefs.linespacing*(*i)->charHeight()/100,i++)
{
if (y<0) continue;
unsigned int marginTop=(*i)->props.get_marginTop(prefsdy);
unsigned int marginBottom=(*i)->props.get_marginBottom(prefsdy);
// When the alignment or marginTop or marginL changes, it's a new paragraph.
if ((*i)->props.alignment>0 && ((*i)->props.alignment!=old_alignment || old_marginTop!=(*i)->props.marginTop || old_marginL!=(*i)->props.marginL))
{
old_alignment=(*i)->props.alignment;
old_marginTop=(*i)->props.marginTop;
old_marginL=(*i)->props.marginL;
// calculate the height of the paragraph
double hParagraph=0;
for (const_iterator pi=i;pi!=end();pi++)
{
if ((*pi)->props.alignment!=old_alignment || (*pi)->props.marginTop!=old_marginTop || (*pi)->props.marginL!=old_marginL)
break;
if (pi+1!=end() && (*(pi+1))->props.alignment==old_alignment && (*(pi+1))->props.marginTop==old_marginTop && (*(pi+1))->props.marginL==old_marginL)
hParagraph+=(double)prefs.linespacing*(*pi)->charHeight()/100;
else
hParagraph+=(*pi)->height();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -