root/branches/perian-1.1/Subtitles/ssa2html.m

Revision 887, 7.0 kB (checked in by astrange, 6 months ago)

Merge trunk to 1.1 branch.

Line 
1 /*
2  *  ssa2html.m
3  *  SSARender2
4  *
5  *  Created by Alexander Strange on 7/28/07.
6  *  Copyright 2007 __MyCompanyName__. All rights reserved.
7  *
8  */
9
10 #import "SubImport.h"
11 #import "SubParsing.h"
12
13 @interface SubHTMLExporter : SubRenderer
14 {
15         SubContext *sc;
16         @public;
17         NSMutableString *html;
18 }
19
20 @end
21
22 @implementation SubHTMLExporter
23 -(SubHTMLExporter*)init
24 {
25         if (self = [super init])
26         {
27                 html = [[NSMutableString alloc] init];
28                 [html appendString:@"<html>\n"];
29                 [html appendString:@"<head>\n"];
30                 [html appendString:@"<meta http-equiv=\"Content-type\" content=\"text/html; charset=UTF-8\" />\n"];
31         }
32        
33         return self;
34 }
35
36 -(void)completedHeaderParsing:(SubContext*)sc_
37 {
38         sc = sc_;
39         [html appendFormat:@"<title>%@</title>\n",[sc->headers objectForKey:@"Title"]];
40         [html appendString:@"<style type=\"text/css\">\n"];
41         [html appendFormat:@".screen {width: %dpx; height: %dpx; background-color: gray; position: relative}\n.bottom {bottom: 20px; position: absolute} .top {top: 20px; position: absolute}\n",sc->resX,sc->resY];
42 }
43
44 static const NSString *haligns[] = {@"left", @"center", @"right"};
45
46 -(void*)completedStyleParsing:(SubStyle*)s
47 {
48         [html appendFormat:@".%@ {display: inline-block; clear: none;\n",s->name];
49         [html appendFormat:@"font-family: \"%@\"; ",s->fontname];
50         [html appendFormat:@"font-size: %fpt;\n",s->size * (72./96.)];
51         [html appendFormat:@"color: #%X%X%X;\n",(int)(s->primaryColor.red*255.),(int)(s->primaryColor.green*255.),(int)(s->primaryColor.blue*255.)];
52         [html appendFormat:@"-webkit-text-stroke-color: #%X%X%X;\n",(int)(s->outlineColor.red*255.),(int)(s->outlineColor.green*255.),(int)(s->outlineColor.blue*255.)];
53         [html appendFormat:@"letter-spacing: %fpx;\n",s->tracking];
54 //      [html appendFormat:@"-webkit-text-stroke-width: %fpx;\n",s->outlineRadius];
55         [html appendFormat:@"text-shadow: #%X%X%X %fpx %fpx 0;\n",(int)(s->shadowColor.red*255.),(int)(s->shadowColor.green*255.),(int)(s->shadowColor.blue*255.),
56                                           s->shadowDist*2., s->shadowDist*2.];
57         [html appendFormat:@"text-outline: #%X%X%X %fpx 0;\n",(int)(s->shadowColor.red*255.),(int)(s->shadowColor.green*255.),(int)(s->shadowColor.blue*255.),
58                 s->outlineRadius];
59         [html appendFormat:@"width: %dpx;\n",sc->resX - s->marginL - s->marginR];
60         [html appendFormat:@"font-weight: %@; font-style: %@; text-decoration: %@;\n",s->bold ? @"bold" : @"normal", s->italic ? @"italic" : @"normal", s->underline ? @"underline" : (s->strikeout ? @"line-through" : @"none")];
61         [html appendFormat:@"text-align: %@;\n", haligns[s->alignH]];
62         [html appendString:@"}\n"];
63        
64         return nil;
65 }
66
67 -(void)endOfHead
68 {
69         [html appendString:@"</style>\n"];
70         [html appendString:@"</head>\n"];
71         [html appendString:@"<body>\n"];
72 }
73
74 NSString *htmlfilter(NSString *s)
75 {
76         NSMutableString *ms = [s mutableCopy];
77        
78         [ms replaceOccurrencesOfString:@"\n" withString:@"<br>" options:0 range:NSMakeRange(0, [ms length])];
79 //      [ms replaceOccurrencesOfString:[NSString stringWithFormat:@"%C",0x00A0] withString:@"&nbsp;" options:0 range:NSMakeRange(0, [ms length])];
80         return ms;
81 }
82
83 -(void*)spanExtraFromRenderDiv:(SubRenderDiv*)div
84 {
85         return [NSMutableString string];
86 }
87
88 -(void*)cloneSpanExtra:(SubRenderSpan*)span
89 {
90         return [NSMutableString string];
91 }
92
93 -(void)spanChangedTag:(SSATagType)tag span:(SubRenderSpan*)span div:(SubRenderDiv*)div param:(void*)p
94 {
95         NSMutableString *sty = span->ex;
96         int ip;
97         NSString *sp;
98         float fp;
99        
100                
101 #define iv() ip = *(int*)p;
102 #define sv() sp = *(NSString**)p;
103 #define fv() fp = *(float*)p;
104 #define cv() ip = *(int*)p; ip = EndianU32_BtoL(ip); ip = ip & 0xFFFFFF;
105        
106         switch (tag) {
107                 case tag_b:
108                         iv();
109                         [sty appendFormat:@"font-weight: %@; ", ip? @"bold" : @"normal"];
110                         break;
111                 case tag_i:
112                         iv();
113                         [sty appendFormat:@"font-style: %@; ", ip? @"italic" : @"normal"];
114                         break;
115                 case tag_u:
116                         iv();
117                         [sty appendFormat:@"text-decoration: %@; ", ip? @"underline" : @"none"];
118                         break;
119                 case tag_s:
120                         iv();
121                         [sty appendFormat:@"text-decoration: %@; ", ip? @"line-through" : @"none"];
122                         break;
123                 case tag_fn:
124                         sv();
125                         [sty appendFormat:@"font-family: %@; ", sp];
126                         break;
127                 case tag_fs:
128                         fv();
129                         [sty appendFormat:@"font-size: %fpt; ", fp * (72./96.)];
130                         break;
131                 case tag_1c:
132                         cv();
133                         [sty appendFormat:@"color: #%0.9X; ", ip];
134                         break;
135                 case tag_4c:
136                         cv();
137                         [sty appendFormat:@"text-shadow: #%0.9X %fpx %fpx 0; ", ip, div->styleLine->shadowDist*2., div->styleLine->shadowDist*2.];
138                         break;
139                 default:
140                         NSLog(@"unimplemented tag type %d",tag);
141         }
142 }
143
144 -(void)htmlifyDivArray:(NSArray*)divs
145 {
146         int div_count = [divs count], i;
147         for (i = 0; i < div_count; i++) {
148                 SubRenderDiv *div = [divs objectAtIndex:i];
149                 int j, spancount = [div->spans count], spans = 1, close_div = 0;
150                
151                 if (div->posX > -1) {
152                         [html appendFormat:@"<div style=\"top: %dpx; left: %dpx; position: absolute\">", div->posY, div->posX];
153                         close_div = 1;
154                 }
155                                
156                 [html appendFormat:@"<span class=\"%@\">", div->styleLine->name];
157                
158                 for (j = 0; j < spancount; j++) {
159                         SubRenderSpan *span = [div->spans objectAtIndex:j];
160                         NSMutableString *ex = span->ex;
161                         int exl = [ex length];
162                        
163                         if (exl) {[html appendFormat:@"<span style=\"%@\">",ex]; spans++;}
164                         [html appendString:htmlfilter([div->text substringWithRange:NSMakeRange(span->offset, ((j == (spancount-1)) ? [div->text length] : ((SubRenderSpan*)[div->spans objectAtIndex:j+1])->offset) - span->offset)])];
165                 }
166                
167                 while (spans--) [html appendString:@"</span>"];
168                 if (close_div) [html appendString:@"</div>"];
169                 [html appendString:@"\n"];
170         }
171 }
172
173 -(void)addSub:(SubLine*)sl
174 {       
175         unichar *ubuf = malloc(sizeof(unichar) * [sl->line length]);
176         NSArray *divs = SubParsePacket(sl->line, sc, self, ubuf);
177         free(ubuf);
178         NSMutableArray *top = [NSMutableArray array], *bot = [NSMutableArray array], *abs = [NSMutableArray array];
179         int div_count = [divs count], i;
180        
181         [html appendString:@"<div class=\"screen\">\n"];
182
183         for (i = 0; i < div_count; i++) {
184                 SubRenderDiv *div = [divs objectAtIndex:i];
185                
186                 if (div->posX > -1) [abs addObject:div]; else if (div->alignV == kSubAlignmentTop) [top addObject:div]; else [bot insertObject:div atIndex:0];
187         }
188        
189         if ([top count]) {
190                 [html appendString:@"<div class=\"top\">\n"];
191                 [self htmlifyDivArray:top];
192                 [html appendString:@"</div>\n"];
193         }
194        
195         if ([bot count]) {
196                 [html appendString:@"<div class=\"bottom\">\n"];
197                 [self htmlifyDivArray:bot];
198                 [html appendString:@"</div>\n"];
199         }
200        
201         [self htmlifyDivArray:abs];
202        
203         [html appendString:@"</div>\n"];
204
205         [html appendString:@"<br>\n"];
206 }
207
208 -(void)endOfFile
209 {
210         [html appendString:@"</body></html>"];
211 }
212 @end
213
214 int main(int argc, char *argv[])
215 {
216         NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
217         SubContext *sc; SubSerializer *ss;
218         SubHTMLExporter *htm = [[SubHTMLExporter alloc] init];
219        
220         SubLoadSSAFromPath([NSString stringWithUTF8String:argv[1]],&sc,&ss,htm);
221        
222         [htm endOfHead];
223        
224         while (![ss isEmpty]) {
225                 NSAutoreleasePool *pool2 = [[NSAutoreleasePool alloc] init];
226
227                 SubLine *sl = [ss getSerializedPacket];
228                 if ([sl->line length] == 1) continue;
229                
230                 [htm addSub:sl];
231                 [pool2 release];
232         }
233        
234         [htm endOfFile];
235        
236         printf([htm->html UTF8String]);
237         [pool release];
238         return 0;
239 }
Note: See TracBrowser for help on using the browser.