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

📄 dvdsubber-compile.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/***********************************************************************
 Copyright 2002 Ben Rudiak-Gould.

 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA,
 or visit <http://www.gnu.org/copyleft/gpl.html>.
***********************************************************************/


#include <string.h>
#include "DVDSubber-compile.h"
#include "DVDSubber-format.h"
#include "DVDSubber-render.h"
#include "DVDSubber-encode.h"

#include <algorithm>
using namespace std;


template<class T> static inline T Min(T a, T b) { return a<b?a:b; }
template<class T> static inline T Max(T a, T b) { return a<b?b:a; }


ICompilerCallbacks* g_compiler_callbacks;


/********************************************************************
********************************************************************/


class DataVectorBase {
protected:
   unsigned char* data;
   unsigned len;
public:
   DataVectorBase() { data = 0; len = 0; }
   ~DataVectorBase() { delete[] data; }
   void grow();
};

void DataVectorBase::grow() {
   unsigned new_len = len ? len*2 : 4096;
   unsigned char* new_data = new unsigned char[new_len];
   memcpy(new_data, data, len);
   delete[] data;
   data = new_data;
   len = new_len;
}

template<class T>
class DataVector : public DataVectorBase {
   unsigned n;
public:
   DataVector() { n = 0; }
   unsigned size() const { return n; }
   T* begin() { return (T*)data; }
   T* end() { return (T*)data + n; }
   void push_back(const T& datum) {
      if ((n+1)*sizeof(T) > len)
         grow();
      ((T*)data)[n++] = datum;
   }
};


/********************************************************************
********************************************************************/


const wchar_t UNICODE_REPLACEMENT = 0xFFFD;

int UTF8toUTF16(wchar_t* dst, const char* _src) {
   const unsigned char* src = (const unsigned char*)_src;
   int dst_pos = 0;
   for (;;) {
      unsigned char ch = *src++;
      if (ch < 0x80) {
         dst[dst_pos] = ch;
         if (ch == 0) {
            break;
         }
         ++dst_pos;
      } else if (ch < 0xC0) {
         dst[dst_pos++] = UNICODE_REPLACEMENT;
      } else {
         unsigned uch = ch;
         int additional = 0;
         while (*src >= 0x80 && *src < 0xC0) {
            uch = (uch << 6) + (*src & 63);
            ++src;
            ++additional;
         }
         unsigned mask_bits = 32 - 6 - additional*5;
         uch &= 0xFFFFFFFFU >> mask_bits;
         unsigned minimum_for_this_encoding = (0x8000000 >> mask_bits);
         static const unsigned char first_byte_range[] = { 0xC0, 0xE0, 0xF0, 0xF8 };

         if (additional < 1 || additional > 3
                         || ch < first_byte_range[additional-1]
                         || ch >= first_byte_range[additional]
                         || uch < 0x80 || uch < minimum_for_this_encoding
                         || (uch >= 0xD800 && uch < 0xE000)
                         || uch > 0x10FFFF)
         {
            uch = UNICODE_REPLACEMENT;
         }

         if (uch < 0x10000) {
            dst[dst_pos] = (wchar_t)uch;
         } else {
            uch -= 0x10000;
            dst[dst_pos++] = 0xD800 + (uch >> 10);
            dst[dst_pos] = 0xDC00 + (uch & 1023);
         }
         ++dst_pos;
      }
   }
   return dst_pos;
}


/********************************************************************
********************************************************************/


class Subber {
   struct Macro {
      Macro* next;
      int type;
      char* data;
   };
   struct Macros {
      Macros* next;
      char* name;
      Macro* body;
   };
   Macros* macros;
   Macro** recording;

   wchar_t fontname[32];
   int size;
   bool bold, italic;
   unsigned char textcolor, halocolor;
   int linespacing;
   int base_field;
   int time0, time1, time2, time3;
   int linealign, boxalign;
   int boxleft, boxright, boxtop, boxbottom;
   bool vertical;
   bool on;
   bool got_vts, got_font, got_size, got_color, got_textbox, got_at;

   Drawable* boxen[30];
   Drawable* lines;
   Drawable* line;

   int ColorLookup(unsigned c) {
      unsigned alpha = c >> 24;
      if (alpha == 0) return 0;
      unsigned rgb = c & 0xFFFFFF;
      int index = g_compiler_callbacks->ColorLookup(rgb);
      if (index >= 0)
         return index + alpha*16;
      else
         throw "too many colors";
   }

   void CloseBox() {
      if (line) {
         lines = lines ? new_TextLines(lines, line, linealign) : line;
         line = 0;
      }
      if (lines) {
         Drawable* box = new_TextBox(lines, boxleft, boxtop, boxright, boxbottom, linealign, boxalign, vertical);
         for (int n=0; ; ++n) {
            if (boxen[n]) {
               box = new_TextBoxen(box, boxen[n]);
               boxen[n] = 0;
            } else {
               boxen[n] = box;
               break;
            }
         }
         lines = 0;
      }
   }

public:

   int error_line_no;
   unsigned error_time;

   Subber() {
      error_line_no = 1;
      error_time = 0;

      macros = 0;
      recording = 0;

      base_field = 0;
      bold = false;
      italic = false;
      linespacing = 0;
      on = true;
      got_at = got_textbox = got_color = got_size = got_font = false;
      memset(boxen, 0, sizeof(boxen));
      lines = 0;
      line = 0;
   }

   ~Subber() {
      for (int i=0; i<30; ++i) {
         delete boxen[i];
      }
      delete lines;
      delete line;
   }

   int GetSegment(FILE* f, char* buf, int buflen);
   void ParseText(char* bytes);
   void ParseCmd(char* bytes);
   void ParseLineBreak();
   void ParseSegment(int type, char* bytebuf);
   void ParseFile(FILE* f);

   void CmdText(const wchar_t* text) {
      if (!(got_vts & got_font & got_size & got_color & got_textbox & got_at))
         throw "Must have <vts>, <font>, <size>, <color>, <box>, and <at> before the first text";
      if (!on) return;
      FontInfo* font = LoadFont(fontname, size, bold, italic);
      // cast away const to fix broken gcc wcsdup prototype
      Drawable* phrase = new_Text(wcsdup((wchar_t*)text), font, textcolor, halocolor, linespacing, time0, time1, time2, time3);
      line = line ? new_TextLine(line, phrase) : phrase;
   }
   void CmdLineBreak() {
      if (!on) return;
      if (!line) {
         CmdText(L"");
      }
      lines = lines ? new_TextLines(lines, line, linealign) : line;
      line = 0;
   }
   void CmdVTS(const int* pvtsn, const wchar_t*) {
      g_compiler_callbacks->SetVTSNumber(*pvtsn);
      got_vts = true;
   }
   void CmdAngle(const int* pangle, const wchar_t*) {
      g_compiler_callbacks->SetAngle(*pangle);
   }
   void CmdFont(const int*, const wchar_t* fontname) {
      // check length!
      if (wcslen(fontname) >= 32) {
         throw "font name too long!";
      } else {
         wcscpy(this->fontname, fontname);
         got_font = true;
      }
   }
   void CmdSize(const int* psize, const wchar_t*) {
      size = *psize;
      got_size = true;
   }
   void CmdLinespacing(const int* pspacing, const wchar_t*) {
      linespacing = *pspacing;
   }
   void CmdColor(const int* colors, const wchar_t*) {
      textcolor = ColorLookup(colors[0]);
      halocolor = ColorLookup(colors[1]);
      got_color = true;
   }
   void CmdItalicOn(const int*, const wchar_t*) {
      italic = true;
   }
   void CmdItalicOff(const int*, const wchar_t*) {
      italic = false;
   }
   void CmdBoldOn(const int*, const wchar_t*) {
      bold = true;
   }
   void CmdBoldOff(const int*, const wchar_t*) {
      bold = false;
   }
   void CmdTextbox(const int* dims, const wchar_t* alignment);
   void CmdFillbox(const int* args, const wchar_t*) {
   }
   void CmdBasefield(const int* pbase, const wchar_t*) {
      base_field = *pbase;
   }
   void At(unsigned fadein_time, unsigned full_time, unsigned fadeout_time, unsigned off_time);
   void CmdAt(const int* times, const wchar_t*);
   void CmdFadeat(const int* times, const wchar_t*);
   void CmdOn(const int*, const wchar_t*) {
      on = true;
   }
   void CmdOff(const int*, const wchar_t*) {
      on = false;
   }

   bool Run();
};


void Subber::CmdTextbox(const int* dims, const wchar_t* alignment) {
   CloseBox();
   boxleft = dims[0];
   boxright = dims[1];
   boxtop = dims[2];
   boxbottom = dims[3];
   vertical = false;
   if (*alignment == L'-') {
      vertical = true;
      ++alignment;
   }
   if (alignment[0] >= L'1' && alignment[0] <= L'9') {
      boxalign = alignment[0] - '1';
   } else {
      throw "Bad alignment value";
   }
   switch (alignment[1]) {
      case 'L': case 'T': linealign = -1; break;
      case 'C': case 'M': linealign =  0; break;
      case 'R': case 'B': linealign = +1; break;
      default: throw "Bad alignment value";
   }
   if (vertical) {
      int t = boxleft; boxleft = boxtop; boxtop = 720-boxright; boxright = boxbottom; boxbottom = 720-t;
      static unsigned char rotate[9] = { 2, 5, 8, 1, 4, 7, 0, 3, 6 };
      boxalign = rotate[boxalign];
   }
   got_textbox = true;
}

void Subber::At(unsigned fadein_time, unsigned full_time, unsigned fadeout_time, unsigned off_time) {
   if (fadein_time > full_time || full_time > fadeout_time || fadeout_time > off_time) {
      throw "subtitle display times are backwards";
   } else if (fadein_time >= off_time) {
      throw "subtitle on and off times are the same";
   }

⌨️ 快捷键说明

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