modified: makefile
[GalaxyCodeBases.git] / tools / Bilibili / danmaku2ass_native / AssClass.cpp
bloba73f685326a50410d8be5f4491f411d7165d2091
1 //
2 // AssClass.cpp
3 // danmaku2ass_native
4 //
5 // Created by TYPCN on 2015/4/8.
6 //
7 //
9 #include "AssClass.hpp"
10 #include <string.h>
11 #include <math.h>
12 #include <algorithm>
13 #include <vector>
14 #include <iostream>
15 #include <sstream>
16 #include <time.h>
18 using namespace std;
20 void Ass::init(const char *filename){
21 std::remove(filename);
22 out.open(filename);
25 void Ass::SetDuration(int dm,int ds){
26 duration_marquee = dm;
27 duration_still = ds;
30 void Ass::WriteHead(int width,int height,const char *font,float fontsize,float alpha){
32 srand((int)time(0));
34 FontSize = fontsize;
35 VideoHeight = height;
36 VideoWidth = width;
38 // Write a♂ss head info
39 out << "[Script Info]\nScript Updated By: Danmaku2ASS_native (https://github.com/typcn/danmaku2ass_native)\nScriptType: v4.00+" << endl;
40 out << "PlayResX: " << width << endl;
41 out << "PlayResY: " << height << endl;
42 out << "Aspect Ratio: " << width << ":" << height << endl;
43 out << "Collisions: Normal" << endl;
44 out << "WrapStyle: 2" << endl;
45 out << "ScaledBorderAndShadow: yes" << endl;
46 out << "YCbCr Matrix: TV.601" << endl << endl;
48 char alpha_hex[3];
49 sprintf(alpha_hex, "%02X", 255-round_int(alpha*255));
51 // Write ass styles , maybe disorder , See https://en.wikipedia.org/wiki/SubStation_Alpha
52 out << "[V4+ Styles]"<< endl;
53 out << "Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding"<< endl;
55 // Get Style name
56 stringstream ss;
57 ss << "TYCM_" << rand() % (int)(9999 + 1);
58 ss >> style_name;
60 out << "Style: " <<
61 style_name << "," << // Style name
62 font << ", " << // Font name
63 fontsize << ", " << // Font size
64 "&H"<< alpha_hex <<"FFFFFF, " << // Primary Color
65 "&H"<< alpha_hex <<"FFFFFF, " << // Secondary Color
66 "&H"<< alpha_hex <<"000000, " << // Outline Color
67 "&H"<< alpha_hex <<"000000, " << // Back Color
68 "0, 0, 0, 0, 100, 100, 0.00, 0.00, 1, 1, 0, 7, 0, 0, 0, 0" << endl << endl;
70 out << "[Events]" << endl;
71 out << "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text" << endl;
74 void Ass::AppendComment(float appear_time,int comment_mode,int font_color,const char *content){
75 int duration;
77 string str = content;
79 stripStr(str);
81 size_t strLength = Utf8StringSize(str);
83 if(strLength > 100){
84 return;
87 int ContentFontLen = (int)strLength*FontSize;
89 char effect[30];
90 if(comment_mode < 4){
91 sprintf(effect,"\\move(%d, [MROW], %d, [MROW])",VideoWidth,-ContentFontLen);
92 duration = duration_marquee;
93 }else if(comment_mode == 4){
94 sprintf(effect,"\\an2\\pos(%d,[BottomROW])",VideoWidth/2);
95 duration = duration_still;
96 }else if(comment_mode == 5){
97 sprintf(effect,"\\an8\\pos(%d,[TopROW])",VideoWidth/2);
98 duration = duration_still;
99 }else{
100 return;
102 string effectStr(effect);
103 string color = "";
104 if(font_color != 16777215){
105 if(font_color == 0x000000){
106 color = "\\c&H000000&";
107 }else if(font_color == 0xffffff){
108 color = "\\c&HFFFFFF&";
109 }else{
110 int R = (font_color >> 16) & 0xff;
111 int G = (font_color >> 8) & 0xff;
112 int B = font_color & 0xff;
113 char hexcolor[7];
114 sprintf(hexcolor, "%02X%02X%02X",B,G,R);
115 hexcolor[6] = '\0';
116 string strcolor(hexcolor);
117 color = "\\c&H" + strcolor + "&";
121 stringstream ss;
122 ss << "Dialogue: 2," << TS2t(appear_time) << "," << TS2t(appear_time + duration) << "," << style_name << ",,0000,0000,0000,,{" << effectStr << color << "}" << str;
124 pair<int,std::string> contentPair = make_pair(ContentFontLen,ss.str());
126 comment_map.insert( std::pair<float, std::pair<int,std::string>>(appear_time,contentPair) );
130 inline void Ass::stripStr(string in){
131 std::replace(in.begin(), in.end(), '\r', '\n');
132 std::replace(in.begin(), in.end(), '\n', ' ');
135 int Ass::round_int( double r ) {
136 return (r > 0.0) ? (r + 0.5) : (r - 0.5);
139 inline string Ass::TS2t(double timestamp){
141 int ts= (int)timestamp*100.0;
142 int hour,minute,second,centsecond;
143 hour = ts/360000;
144 minute = ts%360000;
145 second = minute%6000;
146 minute = minute/6000;
147 centsecond = second%100;
148 second = second/100;
149 char buff[20];
150 sprintf(buff,"%d:%02d:%02d.%02d", hour,minute,second,centsecond);
151 return string(buff);
154 template<typename _Iterator1, typename _Iterator2>
155 inline size_t IncUtf8StringIterator(_Iterator1& it, const _Iterator2& last) {
156 if(it == last) return 0;
157 unsigned char c;
158 size_t res = 1;
159 for(++it; last != it; ++it, ++res) {
160 c = *it;
161 if(!(c&0x80) || ((c&0xC0) == 0xC0)) break;
164 return res;
167 inline size_t Ass::Utf8StringSize(const std::string& str) {
168 size_t res = 0;
169 std::string::const_iterator it = str.begin();
170 for(; it != str.end(); IncUtf8StringIterator(it, str.end()))
171 res++;
173 return res;
176 static inline std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
177 size_t start_pos = 0;
178 while((start_pos = str.find(from, start_pos)) != std::string::npos) {
179 str.replace(start_pos, from.length(), to);
180 start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
182 return str;
185 void Ass::WriteToDisk(std::vector<int> disallowModes){
187 int All_Rows = 0;
188 int Dropped_Rows = 0;
190 typedef std::map<float, pair<int,std::string>>::iterator it_type;
192 float TopTime = 0;
193 float BottomTime = 0;
195 int TopROW = -1;
196 int BottomROW = -1;
198 int line = ceil(VideoHeight/FontSize);
200 double *rows_dismiss_time = new double[line]; // The time of scroll comment dismiss
201 double *rows_visible_time = new double[line]; // The time of last char visible on screen
203 for (int i = 0 ; i < line; i++) {
204 rows_dismiss_time[i] = 0;
205 rows_visible_time[i] = 0;
208 bool removeMRow = 0;
209 bool removeTRow = 0;
210 bool removeBRow = 0;
211 for (auto i = disallowModes.begin();i != disallowModes.end(); i++ ){
212 int mode = *i;
213 if(mode == 1){
214 removeMRow = 1;
215 }else if(mode == 2){
216 removeTRow = 1;
217 }else if(mode == 3){
218 removeBRow = 1;
222 for(it_type iterator = comment_map.begin(); iterator != comment_map.end(); iterator++) {
224 All_Rows++;
226 string r = iterator->second.second;
228 int playbackTime = iterator->first;
229 double TextWidth = iterator->second.first + 2.0; // Add some space between texts
230 double act_time = TextWidth / (((double)VideoWidth + TextWidth)/ (double)duration_marquee); // duration of last char visible on screen
232 if(r.find("[MROW]") != std::string::npos){
233 if(removeMRow){
234 continue;
236 bool Replaced = false;
237 for(int i=0;i < line;i++){
238 double Time_Arrive_Border = (playbackTime + (double)duration_marquee) - act_time; // The time of first char reach left border of video
239 if(Time_Arrive_Border > rows_dismiss_time[i] && playbackTime > rows_visible_time[i]){
240 rows_dismiss_time[i] = playbackTime + (double) duration_marquee;
241 rows_visible_time[i] = playbackTime + act_time;
242 r = ReplaceAll(r,"[MROW]",to_string(i*FontSize));
243 Replaced = true;
244 break;
247 if(!Replaced){
248 r = "";
249 Dropped_Rows++;
251 }else if(r.find("[TopROW]") != std::string::npos){
252 if(removeTRow){
253 continue;
255 float timeago = iterator->first - TopTime;
256 if(timeago > duration_still){
257 TopROW = 0;
258 TopTime = iterator->first;
259 }else{
260 TopROW++;
262 r = ReplaceAll(r,"[TopROW]",to_string(TopROW*FontSize));
263 }else if(r.find("[BottomROW]") != std::string::npos){
264 if(removeBRow){
265 continue;
266 }else{
267 float timeago = iterator->first - BottomTime;
268 if(timeago > duration_still){
269 BottomROW = 0;
270 BottomTime = iterator->first;
271 }else{
272 BottomROW++;
274 r = ReplaceAll(r,"[BottomROW]",to_string(VideoHeight-BottomROW*FontSize));
276 }else{
277 continue;
280 if(r.length() < 10){
281 Dropped_Rows++;
282 continue;
285 out << r << endl;
288 cout << "Comments:" << All_Rows << " Dropped:" << Dropped_Rows << endl;
289 delete[] rows_dismiss_time;
290 delete[] rows_visible_time;