/* * ssa2html * Created by Alexander Strange on 7/28/07. * * A primitive .ssa/.ass to HTML converter. * * This file is part of Perian. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #import "SubImport.h" #import "SubParsing.h" @interface SubHTMLExporter : SubRenderer { SubContext *sc; @public; NSMutableString *html; } @end @implementation SubHTMLExporter -(SubHTMLExporter*)init { if (self = [super init]) { html = [[NSMutableString alloc] init]; [html appendString:@"\n"]; [html appendString:@"\n"]; [html appendString:@"\n"]; [html appendString:@"\n"]; } return self; } -(void)dealloc { [sc release]; [html release]; [super dealloc]; } -(void)completedHeaderParsing:(SubContext*)sc_ { sc = sc_; [html appendFormat:@"%@\n",[sc->headers objectForKey:@"Title"]]; [html appendString:@"\n"]; [html appendString:@"\n"]; [html appendString:@"\n"]; } NSString *htmlfilter(NSString *s) { NSMutableString *ms = [[s mutableCopy] autorelease]; [ms replaceOccurrencesOfString:@"\n" withString:@"
\n" options:0 range:NSMakeRange(0, [ms length])]; // [ms replaceOccurrencesOfString:[NSString stringWithFormat:@"%C",0x00A0] withString:@" " options:0 range:NSMakeRange(0, [ms length])]; return ms; } -(void*)spanExtraFromRenderDiv:(SubRenderDiv*)div { return [[NSMutableString string] retain]; } -(void*)cloneSpanExtra:(SubRenderSpan*)span { return [[NSMutableString string] retain]; } -(void)releaseSpanExtra:(void*)ex { NSMutableString *s = (NSMutableString*)ex; [s release]; } -(void)spanChangedTag:(SSATagType)tag span:(SubRenderSpan*)span div:(SubRenderDiv*)div param:(void*)p { NSMutableString *sty = span->ex; int ip; NSString *sp; float fp; #define iv() ip = *(int*)p; #define sv() sp = *(NSString**)p; #define fv() fp = *(float*)p; #define cv() ip = *(int*)p; ip = EndianU32_BtoL(ip); ip = ip & 0xFFFFFF; switch (tag) { case tag_b: iv(); [sty appendFormat:@"font-weight: %@; ", ip? @"bold" : @"normal"]; break; case tag_i: iv(); [sty appendFormat:@"font-style: %@; ", ip? @"italic" : @"normal"]; break; case tag_u: iv(); [sty appendFormat:@"text-decoration: %@; ", ip? @"underline" : @"none"]; break; case tag_s: iv(); [sty appendFormat:@"text-decoration: %@; ", ip? @"line-through" : @"none"]; break; case tag_fn: sv(); [sty appendFormat:@"font-family: %@; ", sp]; break; case tag_fs: fv(); //this is wrong, see GetWinFontSizeScale() [sty appendFormat:@"font-size: %fpt; ", fp * (72./96.)]; break; case tag_1c: cv(); [sty appendFormat:@"color: #%0.9X; ", ip]; break; case tag_4c: cv(); [sty appendFormat:@"text-shadow: #%0.9X %fpx %fpx 0; ", ip, div->styleLine->shadowDist*2., div->styleLine->shadowDist*2.]; break; default: NSLog(@"unimplemented tag type %d",tag); } } -(void)htmlifyDivArray:(NSArray*)divs { int div_count = [divs count], i; for (i = 0; i < div_count; i++) { SubRenderDiv *div = [divs objectAtIndex:i]; int j, spancount = [div->spans count], spans = 1, close_div = 0; if (div->positioned) { [html appendFormat:@"
", div->posY, div->posX]; close_div = 1; } [html appendFormat:@"", EscapeCSSIdentifier(div->styleLine->name)]; for (j = 0; j < spancount; j++) { SubRenderSpan *span = [div->spans objectAtIndex:j]; NSMutableString *ex = span->ex; int exl = [ex length]; if (exl) {[html appendFormat:@"",ex]; spans++;} [html appendString:htmlfilter([div->text substringWithRange:NSMakeRange(span->offset, ((j == (spancount-1)) ? [div->text length] : ((SubRenderSpan*)[div->spans objectAtIndex:j+1])->offset) - span->offset)])]; } while (spans--) [html appendString:@""]; if (close_div) [html appendString:@"
"]; [html appendString:@"\n"]; } } -(void)addSub:(SubLine*)sl { unichar *ubuf = malloc(sizeof(unichar) * [sl->line length]); NSArray *divs = SubParsePacket(sl->line, sc, self); free(ubuf); NSMutableArray *top = [NSMutableArray array], *bot = [NSMutableArray array], *abs = [NSMutableArray array]; int div_count = [divs count], i; [html appendString:@"
\n"]; for (i = 0; i < div_count; i++) { SubRenderDiv *div = [divs objectAtIndex:i]; if (div->positioned) [abs addObject:div]; else if (div->alignV == kSubAlignmentTop) [top addObject:div]; else [bot insertObject:div atIndex:0]; } if ([top count]) { [html appendString:@"
\n"]; [self htmlifyDivArray:top]; [html appendString:@"
\n"]; } if ([bot count]) { [html appendString:@"
\n"]; [self htmlifyDivArray:bot]; [html appendString:@"
\n"]; } [self htmlifyDivArray:abs]; [html appendString:@"
\n"]; [html appendString:@"
\n"]; } -(void)endOfFile { [html appendString:@"\n"]; } @end int main(int argc, char *argv[]) { if (argc != 2) return 1; NSAutoreleasePool *outer_pool = [[NSAutoreleasePool alloc] init]; SubContext *sc; SubSerializer *ss = [[SubSerializer alloc] init]; SubHTMLExporter *htm = [[SubHTMLExporter alloc] init]; NSAutoreleasePool *inner_pool = [[NSAutoreleasePool alloc] init]; //start of lameness //it should only have to call subparsessafile here, or something NSString *header = LoadSSAFromPath([NSString stringWithUTF8String:argv[1]], ss); [ss setFinished:YES]; NSDictionary *headers; NSArray *styles; SubParseSSAFile(header, &headers, &styles, NULL); sc = [[SubContext alloc] initWithHeaders:headers styles:styles delegate:htm]; //end(?) of lameness //other part of lameness: some sub objects are autoreleased instead of manually released //fix this so inner_pool can be deleted [htm endOfHead]; while (![ss isEmpty]) { SubLine *sl = [ss getSerializedPacket]; if ([sl->line length] == 1) continue; [htm addSub:sl]; } [htm endOfFile]; puts([htm->html UTF8String]); [inner_pool release]; [ss release]; [htm release]; [outer_pool release]; return 0; }