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

📄 dvdsubber-compile.cpp

📁 DVD工具dvdsynth的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
   time0 = fadein_time + base_field;
   time1 = full_time + base_field;
   time2 = fadeout_time + base_field;
   time3 = off_time + base_field;
   got_at = true;
}

void Subber::CmdAt(const int* times, const wchar_t*) {
   At(times[0], times[0], times[1], times[1]);
}

void Subber::CmdFadeat(const int* times, const wchar_t*) {
   At(times[0], times[1], times[2], times[3]);
}

bool Subber::Run() {
   CloseBox();
   // merge boxen into one big tree
   int b;
   for (b=0; b<30; ++b) {
      if (boxen[b]) break;
   }
   Drawable* all_boxes = boxen[b];
   boxen[b] = 0;
   for (++b; b<30; ++b) {
      if (boxen[b]) {
         all_boxes = new_TextBoxen(all_boxes, boxen[b]);
         boxen[b] = 0;
      }
   }
   if (!all_boxes) {
      throw "no text to render!";
   }

   boxen[0] = all_boxes;

   // find all event times
   int max_events = 4000;
   unsigned* event_time;
   unsigned* event_time_end;
   for (;;) {
      event_time = new unsigned[max_events];
      event_time_end = all_boxes->GetEventTimes(event_time, event_time + max_events);
      if (event_time_end < event_time + max_events) {
         break;
      } else {
         delete[] event_time;
         max_events *= 2;
         continue;
      }
   }

   sort(event_time, event_time_end);

   // uniq in bits 2..31, taking min of bits 0..1
   if (event_time_end > event_time) {
      unsigned* dst = event_time + 1;
      for (unsigned* src = event_time + 1; src < event_time_end; ++src)
         if ((src[0] >> 2) != (src[-1] >> 2))
            *dst++ = *src;
      event_time_end = dst;
   }

   int num_events = event_time_end - event_time;

   bool* event_blank = new bool[num_events];

   int e;
   int blanks = 0;
   for (e=0; e<num_events; ++e) {
      event_blank[e] = ((event_time[e] & 3) == 2) ? all_boxes->NothingToDraw(event_time[e] >> 2) : false;
      blanks += event_blank[e];
   }

   g_compiler_callbacks->NotifySubpictureCount(num_events - blanks);

   bool ntsc = g_compiler_callbacks->IsNTSC();

   bool success = true;

   for (e=0; e<num_events-1; ++e) {
      if (event_blank[e]) {
         continue;
      }

      error_time = event_time[e] >> 2;

      static unsigned char static_buffer[720*576];
      static DrawingBuf buf = { static_buffer, 720, 480, 1, 720 };
      buf.left = buf.width; buf.right = 0;
      buf.top = buf.height; buf.bottom = 0;
      all_boxes->DrawSelf(event_time[e] >> 2, &buf, 0, 0);
      if (buf.left >= buf.right || buf.top >= buf.bottom) {
         continue;
      }

      SubpictureBuf subpicture_buf;
      subpicture_buf.SubpictureOn(0, buf.ptr, buf.left, buf.right, buf.top, buf.bottom, ntsc);
      if (event_blank[e+1]) {
         subpicture_buf.SubpictureOff((event_time[e+1] >> 2) - (event_time[e] >> 2), ntsc);
      }
      const unsigned char* p = subpicture_buf.GetPtr();
      g_compiler_callbacks->AddSubpicture(event_time[e] >> 2, p);

      if (g_compiler_callbacks->UserAborted()) {
         success = false;
         break;
      }
   }
   delete[] event_time;
   delete[] event_blank;
   return success;
}


struct Cmd {
   const char* name;
   const char* args;
   void (Subber::*func) (const int* intargs, const wchar_t* stringarg);
};


Cmd cmds[] = {
   { "font ", "s", &Subber::CmdFont },
   { "size ", "u", &Subber::CmdSize },
   { "linespacing ", "i", &Subber::CmdLinespacing },
   { "color ", "xx", &Subber::CmdColor },
   { "textbox ", "iiiis", &Subber::CmdTextbox },
   { "fillbox ", "uuuux", &Subber::CmdFillbox },
   { "vts ", "u", &Subber::CmdVTS },
   { "angle ", "u", &Subber::CmdAngle },
   { "basefield ", "u", &Subber::CmdBasefield },
   { "at ", "uu", &Subber::CmdAt },
   { "fadeat ", "uuuu", &Subber::CmdFadeat },
   { "i", "", &Subber::CmdItalicOn },
   { "/i", "", &Subber::CmdItalicOff },
   { "b", "", &Subber::CmdBoldOn },
   { "/b", "", &Subber::CmdBoldOff },
   { "on", "", &Subber::CmdOn },
   { "off", "", &Subber::CmdOff },
};


// type: 0=eof, 1=text, 2=<>, 3=|
int Subber::GetSegment(FILE* f, char* buf, int buflen) {
   int ch = getc(f);
   if (ch == EOF) {
      return 0;
   } else if (ch == '|') {
      return 3;
   } else if (ch == '<') {
      int bufpos = 0;
      while ((ch = getc(f)) != '>') {
         if (ch == EOF) {
            throw "\"<\" without matching \">\" at end of file";
         }
         if (ch == '\n') {
            throw "\"<\" without matching \">\"";
         }
         if (bufpos >= buflen-1) {
            throw "Command too long";
         }
         buf[bufpos++] = (ch == '\\') ? getc(f) : ch;
      }
      buf[bufpos] = 0;
      return 2;
   } else {
      int bufpos = 0;
      for (;;) {
         if (ch == '#') {
            do {
               ch = getc(f);
            } while (ch != EOF && ch != '\n');
         }
         if (ch == '\n') {
            ++error_line_no;
         } else if (ch == EOF || ch == '<' || ch == '|') {
            break;
         } else {
            if (bufpos >= buflen-1) {
               throw "Text too long";
            }
            buf[bufpos++] = (ch == '\\') ? getc(f) : ch;
         }
         ch = getc(f);
      }
      if (ch != EOF) {
         ungetc(ch, f);
      }
      buf[bufpos] = 0;
      return 1;
   }
}


void Subber::ParseText(char* bytes) {
   if (recording) {
      Macro* m = new Macro;
      m->type = 1;
      m->data = strdup(bytes);
      *recording = m;
      recording = &m->next;
   } else {
      wchar_t unibuf[1024];
      UTF8toUTF16(unibuf, bytes);
      if (unibuf[0] == 0 || (unibuf[0] == 0xFEFF && unibuf[1] == 0)) {
         return;
      }
      CmdText(unibuf);
   }
}


void Subber::ParseCmd(char* bytes) {
   if (bytes[0] == 0) return;
   if (memcmp(bytes, "def ", 4) == 0) {
      if (recording) {
         throw "nested def";
      } else {
         Macros* m = new Macros;
         m->next = macros;
         macros = m;
         m->name = strdup(bytes+4);
         recording = &m->body;
      }
   } else if (memcmp(bytes, "enddef", 7) == 0) {
      if (recording) {
         *recording = 0;
         recording = 0;
      } else {
         throw "enddef without def";
      }
   } else if (recording) {
      Macro* m = new Macro;
      m->type = 2;
      m->data = strdup(bytes);
      *recording = m;
      recording = &m->next;
   } else {
      for (Macros* m = macros; m; m = m->next) {
         if (strcmp(m->name, bytes) == 0) {
            for (Macro* c = m->body; c; c = c->next) {
               ParseSegment(c->type, c->data);
            }
            return;
         }
      }
      for (int c = 0; c < sizeof(cmds)/sizeof(cmds[0]); ++c) {
         if (memcmp(bytes, cmds[c].name, strlen(cmds[c].name)) == 0) {
            int int_args[8];
            wchar_t unibuf[1024];
            unibuf[0] = 0;
            const char* p = bytes + strlen(cmds[c].name);
            char* q;
            for (int a = 0; cmds[c].args[a]; ++a) {
               if (a > 0) {
                  if (*p++ != ',') throw "expected comma";
               }
               switch (cmds[c].args[a]) {
               case 'i':
                  int_args[a] = strtol(p, &q, 10);
                  break;
               case 'u':
                  int_args[a] = strtoul(p, &q, 10);
                  break;
               case 'x':
                  int_args[a] = strtoul(p, &q, 16);
                  break;
               case 's':
                  UTF8toUTF16(unibuf, p);
                  q = strchr(p, 0);
                  break;
               }
               if (p == q) throw "invalid number";
               p = q;
               while (*p == ' ') ++p;
            }
            if (*p != 0)
               throw "extra junk";
            (this->*cmds[c].func)(int_args, unibuf);
            return;
         }
      }
      puts(bytes);
      throw "Bad command";
   }
}


void Subber::ParseLineBreak() {
   if (recording) {
      Macro* m = new Macro;
      m->type = 3;
      *recording = m;
      recording = &m->next;
   } else {
      CmdLineBreak();
   }
}


void Subber::ParseSegment(int type, char* bytebuf) {
   switch (type) {
   case 1:
      ParseText(bytebuf);
      break;
   case 2:
      ParseCmd(bytebuf);
      break;
   case 3:
      ParseLineBreak();
      break;
   }
}


void Subber::ParseFile(FILE* f) {
   char bytebuf[1024];
   for (;;) {
      int type = GetSegment(f, bytebuf, sizeof(bytebuf));
      if (type == 0) break;
      ParseSegment(type, bytebuf);
   }
}


bool CompileSubtitles(FILE* subfile, ICompilerCallbacks* compiler_callbacks) {
   g_compiler_callbacks = compiler_callbacks;
   compiler_callbacks->Note("Reading the subtitle script...");
   Subber subber;
   try {
      subber.ParseFile(subfile);
   }
   catch (const char* error) {
      compiler_callbacks->ErrorAtLine(error, subber.error_line_no);
      return false;
   }
   compiler_callbacks->NotifyDoneParsing();
   compiler_callbacks->Note("Rendering the subtitles...");
   try {
      return subber.Run();
   }
   catch (const char* error) {
      compiler_callbacks->ErrorAtTime(error, subber.error_time);
      return false;
   }
}

⌨️ 快捷键说明

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