⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tfont.cpp

📁 从FFMPEG转换而来的H264解码程序,VC下编译..
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 2002-2006 Milan Cutka
 *
 * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "stdafx.h"
#include "Tsubreader.h"
#include "TsubtitleText.h"
#include "Tfont.h"
#include "TfontSettings.h"
#include "IffdshowBase.h"
#include "IffdshowDecVideo.h"
#include "TfontManager.h"
#include "simd.h"
#include "Tconfig.h"
#include "ffdebug.h"
#include "postproc/swscale.h"
#include "Tlibmplayer.h"
#include <mbstring.h>
#pragma warning(disable:4244)

//============================ TrenderedSubtitleWordBase =============================
TrenderedSubtitleWordBase::~TrenderedSubtitleWordBase()
{
 if (own)
  for (int i=0;i<3;i++)
   {
    aligned_free(bmp[i]);
    aligned_free(msk[i]);
   }
}

//============================== TrenderedSubtitleWord ===============================

// full rendering
template<class tchar> TrenderedSubtitleWord::TrenderedSubtitleWord(HDC hdc,const tchar *s0,size_t strlens,const short (*matrix)[5],const YUVcolor &yuv,const TrenderedSubtitleLines::TprintPrefs &prefs,int xscale,int alignment):TrenderedSubtitleWordBase(true),shiftChroma(true)
{
 typedef typename tchar_traits<tchar>::ffstring ffstring;
 typedef typename tchar_traits<tchar>::strings strings;
 strings s1;
 strtok(ffstring(s0,strlens).c_str(),_L("\t"),s1);
 SIZE sz;sz.cx=sz.cy=0;ints cxs;
 for (typename strings::iterator s=s1.begin();s!=s1.end();s++)
  {
   SIZE sz0;
   prefs.config->getGDI<tchar>().getTextExtentPoint32(hdc,s->c_str(),(int)s->size(),&sz0);
   sz.cx+=sz0.cx;
   if (s+1!=s1.end())
    {
     int tabsize=prefs.tabsize*sz0.cy;
     int newpos=(sz.cx/tabsize+1)*tabsize;
     sz0.cx+=newpos-sz.cx;
     sz.cx=newpos;
    }
   cxs.push_back(sz0.cx);
   sz.cy=std::max(sz.cy,sz0.cy);
  }
 OUTLINETEXTMETRIC otm;
 GetOutlineTextMetrics(hdc,sizeof(otm),&otm);
 unsigned int shadowSize = getShadowSize(prefs,otm.otmTextMetrics.tmHeight);
 if (otm.otmItalicAngle)
  sz.cx-=LONG(sz.cy*sin(otm.otmItalicAngle*M_PI/1800));
 else
  if (otm.otmTextMetrics.tmItalic)
   sz.cx+=sz.cy*0.35;
 dx[0]=(sz.cx/4+2)*4;dy[0]=sz.cy+4;
 unsigned char *bmp16=(unsigned char*)calloc(dx[0]*4,dy[0]);
 HBITMAP hbmp=CreateCompatibleBitmap(hdc,dx[0],dy[0]);
 HGDIOBJ old=SelectObject(hdc,hbmp);
 RECT r={0,0,dx[0],dy[0]};
 FillRect(hdc,&r,(HBRUSH)GetStockObject(BLACK_BRUSH));
 SetTextColor(hdc,RGB(255,255,255));
 SetBkColor(hdc,RGB(0,0,0));
 int x=2;
 ints::const_iterator cx=cxs.begin();
 for (typename strings::const_iterator s=s1.begin();s!=s1.end();s++,cx++)
  {
   const char *t=(const char *)s->c_str();
   int sz=s->size();
   prefs.config->getGDI<tchar>().textOut(hdc,x,2,s->c_str(),sz/*(int)s->size()*/);
   x+=*cx;
  }
 drawShadow(hdc,hbmp,bmp16,old,xscale,sz,prefs,matrix,yuv,shadowSize,alignment);
}
void TrenderedSubtitleWord::drawShadow(HDC hdc,HBITMAP hbmp,unsigned char *bmp16,HGDIOBJ old,int xscale,const SIZE &sz,const TrenderedSubtitleLines::TprintPrefs &prefs,const short (*matrix)[5],const YUVcolor &yuv,unsigned int shadowSize,int alignment)
{
 BITMAPINFO bmi;
 bmi.bmiHeader.biSize=sizeof(bmi.bmiHeader);
 bmi.bmiHeader.biWidth=dx[0];
 bmi.bmiHeader.biHeight=-1*dy[0];
 bmi.bmiHeader.biPlanes=1;
 bmi.bmiHeader.biBitCount=32;
 bmi.bmiHeader.biCompression=BI_RGB;
 bmi.bmiHeader.biSizeImage=dx[0]*dy[0];
 bmi.bmiHeader.biXPelsPerMeter=75;
 bmi.bmiHeader.biYPelsPerMeter=75;
 bmi.bmiHeader.biClrUsed=0;
 bmi.bmiHeader.biClrImportant=0;
 GetDIBits(hdc,hbmp,0,dy[0],bmp16,&bmi,DIB_RGB_COLORS);  // copy bitmap, get it in bmp16
 SelectObject(hdc,old);
 DeleteObject(hbmp);


 unsigned int _dx,_dy;
 _dx=(xscale*dx[0]/100)/4+4+shadowSize;
 _dy=dy[0]/4+4+shadowSize;
 dxCharY=xscale*sz.cx/400;dyCharY=sz.cy/4;
 _dx=(_dx/8+1)*8;
 bmp[0]=(unsigned char*)aligned_calloc(_dx,_dy);
 msk[0]=(unsigned char*)aligned_calloc(_dx,_dy);
 int dxCharYstart;
 switch (alignment)
  {
   case 1: // left(SSA)
   case 5:
   case 9:
    dxCharYstart=0;
    break;
   case 2: // center(SSA)
   case 6:
   case 10:
    dxCharYstart=(_dx-((sz.cx+3)/4+2+shadowSize)*xscale/100)/2;
    break;
   case 3: // right(SSA)
   case 7:
   case 11:
    dxCharYstart=_dx-((sz.cx+3)/4+2+shadowSize)*xscale/100;
    break;
   case -1:
   default:
    dxCharYstart=((xscale==100 && prefs.align!=ALIGN_LEFT)?(_dx-dx[0]/4)/2:0);
    break;
  }
 if (dxCharYstart<0) dxCharYstart=0;
 for (unsigned int y=2;y<dy[0]-2;y+=4)
  {
   unsigned char *dstBmpY=bmp[0]+(y/4+2)*_dx+2+dxCharYstart;
   for (unsigned int xstep=xscale==100?4*65536:400*65536/xscale,x=(2<<16)+xstep;x<((dx[0]-2)<<16);x+=xstep,dstBmpY++)
    {
     unsigned int sum=0;
     for (const unsigned char *bmp16src=bmp16+((y-2)*dx[0]+((x>>16)-2))*4,*bmp16srcEnd=bmp16src+5*dx[0]*4;bmp16src!=bmp16srcEnd;bmp16src+=dx[0]*4)
	 {
      for (int i=0;i<=12;i+=4)
       sum+=bmp16src[i];
	 }
     sum/=20; // average of 5x4=20pixels
     *dstBmpY=(unsigned char)sum;
    }
  }
 free(bmp16);

#if 0
 // This code works. Blur characters. Edge gets more smooth, outline gets thicker.
 // This code is better adapted to bigger characters.
 if (prefs.deci)
  {
   unsigned char *blured_bmp=(unsigned char*)aligned_calloc(_dx,_dy);
   Tlibmplayer *libmplayer;
   SwsFilter filter;
   SwsParams params;
   prefs.deci->getPostproc(&libmplayer);
   filter.lumH = filter.lumV = filter.chrH = filter.chrV = libmplayer->sws_getGaussianVec(0.7, 3.0);
   libmplayer->sws_normalizeVec(filter.lumH, 1.0);

   Tlibmplayer::swsInitParams(&params,SWS_GAUSS);
   SwsContext *ctx=libmplayer->sws_getContext(_dx, _dy, IMGFMT_Y800, _dx, _dy, IMGFMT_Y800, &params, &filter, NULL);
   libmplayer->sws_scale_ordered(ctx,(const uint8_t**)&bmp[0],(const stride_t *)&_dx,0,_dy,(uint8_t**)&blured_bmp,(stride_t *)&_dx);
   libmplayer->sws_freeContext(ctx);
   libmplayer->sws_freeVec(filter.lumH);
   libmplayer->Release();
   aligned_free(bmp[0]);
   bmp[0]=blured_bmp;
  }
#endif

 dx[0]=_dx;dy[0]=_dy;
 if (!matrix)
  memset(msk[0],255,dx[0]*dy[0]);
 else
  {
   memcpy(msk[0],bmp[0],dx[0]*dy[0]);

	#define MAKE_SHADOW(x,y)                                  \
    {                                                         \
     unsigned int s=0,cnt=0;                                  \
     for (int yy=-2;yy<=+2;yy++)                              \
      {                                                       \
       if (y+yy<0 || (unsigned int)(y+yy)>=dy[0]) continue;   \
       for (int xx=-2;xx<=+2;xx++)                            \
        {                                                     \
         if (x+xx<0 || (unsigned int)(x+xx)>=dx[0]) continue; \
         s+=bmp[0][dx[0]*(y+yy)+(x+xx)]*matrix[yy+2][xx+2];   \
         cnt++;                                               \
        }                                                     \
      }                                                       \
     s/=cnt*32;                                               \
     if (s>255) s=255;                                        \
     msk[0][dx[0]*y+x]=(unsigned char)s;                      \
    }

   int dyY1=dy[0]-1,dyY2=dy[0]-2;
   for (unsigned int x=0;x<dx[0];x++)
    {
     MAKE_SHADOW(x,0);
     MAKE_SHADOW(x,1);
     MAKE_SHADOW(x,dyY2);
     MAKE_SHADOW(x,dyY1);
    }
   int dxY1=dx[0]-1,dxY2=dx[0]-2;
   for (unsigned int y0=2;y0<dy[0]-2;y0++)
    {
     MAKE_SHADOW(0,y0);
     MAKE_SHADOW(1,y0);
     MAKE_SHADOW(dxY2,y0);
     MAKE_SHADOW(dxY1,y0);
    }



   __m64 matrix8_0=*(__m64*)matrix[0],matrix8_1=*(__m64*)matrix[1],matrix8_2=*(__m64*)matrix[2];
   const int matrix4[3]={matrix[0][4],matrix[1][4],matrix[2][4]};
   const unsigned char *bmpYsrc_2=bmp[0],*bmpYsrc_1=bmp[0]+1*dx[0],*bmpYsrc=bmp[0]+2*dx[0],*bmpYsrc1=bmp[0]+3*dx[0],*bmpYsrc2=bmp[0]+4*dx[0];
   unsigned char *mskYdst=msk[0]+dx[0]*2;
   __m64 m0=_mm_setzero_si64();
   for (unsigned int y=2;y<dy[0]-2;y++,bmpYsrc_2+=dx[0],bmpYsrc_1+=dx[0],bmpYsrc+=dx[0],bmpYsrc1+=dx[0],bmpYsrc2+=dx[0],mskYdst+=dx[0])
    for (unsigned int x=2;x<dx[0]-2;x++)
     {
      __m64 r_2=_mm_madd_pi16(_mm_unpacklo_pi8(*(__m64*)(bmpYsrc_2+x-2),m0),matrix8_0);
      __m64 r_1=_mm_madd_pi16(_mm_unpacklo_pi8(*(__m64*)(bmpYsrc_1+x-2),m0),matrix8_1);
      __m64 r  =_mm_madd_pi16(_mm_unpacklo_pi8(*(__m64*)(bmpYsrc  +x-2),m0),matrix8_2);
      __m64 r1 =_mm_madd_pi16(_mm_unpacklo_pi8(*(__m64*)(bmpYsrc1 +x-2),m0),matrix8_1);
      __m64 r2 =_mm_madd_pi16(_mm_unpacklo_pi8(*(__m64*)(bmpYsrc2 +x-2),m0),matrix8_0);
      r=_mm_add_pi32(_mm_add_pi32(_mm_add_pi32(_mm_add_pi32(r_2,r_1),r),r1),r2);
      r=_mm_add_pi32(_mm_srli_si64(r,32),r);
      int s=bmpYsrc_2[x+2]*matrix4[0];
      s+=   bmpYsrc_1[x+2]*matrix4[1];
      s+=   bmpYsrc  [x+2]*matrix4[2];
      s+=   bmpYsrc1 [x+2]*matrix4[1];
      s+=   bmpYsrc2 [x+2]*matrix4[0];
      mskYdst[x]=limit_uint8((_mm_cvtsi64_si32(r)+s)/(25*32));
     }
  }
 dx[1]=dx[0]>>prefs.shiftX[1];dx[2]=dx[0]>>prefs.shiftX[2];
 dy[1]=dy[0]>>prefs.shiftY[1];dy[2]=dy[0]>>prefs.shiftY[2];
 unsigned int _dxUV=dx[1];
 dx[1]=(dx[1]/8+1)*8;
 bmp[1]=(unsigned char*)aligned_calloc(dx[1],dy[1]);msk[1]=(unsigned char*)aligned_calloc(dx[1],dy[1]);
 dx[2]=(dx[2]/8+1)*8;
 bmp[2]=(unsigned char*)aligned_calloc(dx[2],dy[2]);msk[2]=(unsigned char*)aligned_calloc(dx[2],dy[2]);
 unsigned char *bmpptr[3]={NULL,bmp[1],bmp[2]};
 unsigned char *mskptr[3]={NULL,msk[1],msk[2]};
 for (unsigned int y=0;y<dy[1];y++,bmpptr[1]+=dx[1],bmpptr[2]+=dx[2],mskptr[1]+=dx[1],mskptr[2]+=dx[2])
  {
   const unsigned char *bmpYptr=bmp[0]+dx[0]*(y*2),*mskYptr=msk[0]+dx[0]*(y*2);
   for (unsigned int x=0;x<_dxUV;x++,bmpYptr+=2,mskYptr+=2)
    {
     unsigned int s;
     s =bmpYptr[0];
     s+=bmpYptr[1];
     s+=bmpYptr[dx[0]];
     s+=bmpYptr[dx[0]+1];
     bmpptr[1][x]=(unsigned char)((yuv.U*s)>>9);
     bmpptr[2][x]=(unsigned char)((yuv.V*s)>>9);
     s =mskYptr[0];
     s+=mskYptr[1];
     s+=mskYptr[dx[0]];
     s+=mskYptr[dx[0]+1];
     mskptr[1][x]=
     mskptr[2][x]=(unsigned char)(s/8);
    }
  }
 unsigned int cnt=dx[0]*dy[0],i=0;
 __m64 m0=_mm_setzero_si64(),yuvY=_mm_set1_pi16(yuv.Y);
 for (;i<cnt-3;i+=4)
  {
   __m64 bmp8=_mm_unpacklo_pi8(_mm_cvtsi32_si64(*(int*)(bmp[0]+i)),m0);
   bmp8=_mm_srli_pi16(_mm_mullo_pi16(bmp8,yuvY),8);
   *(int*)(bmp[0]+i)=_mm_cvtsi64_si32(_mm_packs_pu16(bmp8,m0));
  }
 for (;i<cnt;i++)
 {
  bmp[0][i]=(unsigned char)((bmp[0][i]*yuv.Y)>>8);
 }
 bmpmskstride[0]=dx[0];bmpmskstride[1]=dx[1];bmpmskstride[2]=dx[2];
 _mm_empty();

   unsigned int shadowAlpha = prefs.shadowAlpha;
   unsigned int shadowMode = prefs.shadowMode; // 0: glowing, 1:classic with gradient, 2: classic with no gradient, >=3: no shadow
   if (shadowSize > 0)
   if (shadowMode == 0) //Gradient glowing shadow (most complex)
   {
	   if (dx[0]<shadowSize) shadowSize=dx[0];
	   if (dy[0]<shadowSize) shadowSize=dy[0];
	   unsigned int circle[1089]; // 1089=(16*2+1)^2
	   if (shadowSize>16) shadowSize=16;
	   int circleSize=shadowSize*2+1;
	   for (int y=0;y<circleSize;y++)
	   {
			for (int x=0;x<circleSize;x++)
			{
				unsigned int rx=ff_abs(x-(int)shadowSize);
				unsigned int ry=ff_abs(y-(int)shadowSize);
				unsigned int r=(unsigned int)sqrt((double)(rx*rx+ry*ry));
				if (r>shadowSize)
					circle[circleSize*y+x] = 0;
				else
					circle[circleSize*y+x] = shadowAlpha*(shadowSize+1-r)/(shadowSize+1);
			}
		}
	   for (unsigned int y=0; y<_dy;y++)
	   {
			int starty = y>=shadowSize ? 0 : shadowSize-y;
			int endy = y+shadowSize<_dy ? circleSize : _dy-y+shadowSize;
			for (unsigned int x=0; x<_dx;x++)
			{
				unsigned int pos = _dx*y+x;
				int startx = x>=shadowSize ? 0 : shadowSize-x;
				int endx = x+shadowSize<_dx ? circleSize : _dx-x+shadowSize;
				if (bmp[0][pos] == 0) continue;
				for (int ry=starty; ry<endy;ry++)
				{
					for (int rx=startx; rx<endx;rx++)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -