source: trunk/Subtitles/SubContext.m @ 1044

Revision 1044, 8.9 KB checked in by astrange, 5 years ago (diff)
  • Add new tool targets ssa2html and detect-encoding.
  • Lift some Xcode settings out of the Perian target into the project.
  • Fix compilation error in FFission.
  • Remove unused variable in SubContext?. (small memory savings)
Line 
1/*
2 * SubContext.m
3 * Created by Alexander Strange on 7/28/07.
4 *
5 * This file is part of Perian.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#import "SubContext.h"
23#import "SubParsing.h"
24
25@implementation SubStyle
26
27SubRGBAColor ParseSSAColor(unsigned rgb)
28{
29        unsigned char r, g, b, a;
30       
31        a = (rgb >> 24) & 0xff;
32        b = (rgb >> 16) & 0xff;
33        g = (rgb >> 8) & 0xff;
34        r = rgb & 0xff;
35       
36        a = 255-a;
37       
38        return (SubRGBAColor){r/255.,g/255.,b/255.,a/255.};
39}
40
41static SubRGBAColor ParseSSAColorString(NSString *c)
42{
43        const char *c_ = [c UTF8String];
44        unsigned int rgb;
45       
46        if (c_[0] == '&') {
47                rgb = strtoul(&c_[2],NULL,16);
48        } else {
49                rgb = strtol(c_,NULL,0);
50        }
51       
52        return ParseSSAColor(rgb);
53}
54
55UInt8 SSA2ASSAlignment(UInt8 a)
56{
57    int h = 1, v = 0;
58        if (a >= 9 && a <= 11) {v = kSubAlignmentMiddle; h = a-8;}
59        if (a >= 5 && a <= 7)  {v = kSubAlignmentTop;    h = a-4;}
60        if (a >= 1 && a <= 3)  {v = kSubAlignmentBottom; h = a;}
61        return v * 3 + h;
62}
63
64void ParseASSAlignment(UInt8 a, UInt8 *alignH, UInt8 *alignV)
65{
66        switch (a) {
67                default: case 1 ... 3: *alignV = kSubAlignmentBottom; break;
68                case 4 ... 6: *alignV = kSubAlignmentMiddle; break;
69                case 7 ... 9: *alignV = kSubAlignmentTop; break;
70        }
71       
72        switch (a) {
73                case 1: case 4: case 7: *alignH = kSubAlignmentLeft; break;
74                default: case 2: case 5: case 8: *alignH = kSubAlignmentCenter; break;
75                case 3: case 6: case 9: *alignH = kSubAlignmentRight; break;
76        }
77}
78
79BOOL ParseFontVerticality(NSString **fontname)
80{
81        if ([*fontname characterAtIndex:0] == '@') {
82                *fontname = [*fontname substringFromIndex:1];
83                //return YES; // XXX vertical
84        }
85        return NO;
86}
87
88+(SubStyle*)defaultStyleWithDelegate:(SubRenderer*)delegate
89{
90        SubStyle *sty = [[[SubStyle alloc] init] autorelease];
91       
92        sty->name = @"*Default";
93        sty->fontname = @"Helvetica";
94        sty->platformSizeScale = 1;
95        sty->size = 32 * sqrt([delegate aspectRatio] / (4./3.));
96        sty->primaryColor = (SubRGBAColor){1,1,1,1};
97        sty->outlineColor = (SubRGBAColor){0,0,0,1};
98        sty->shadowColor = (SubRGBAColor){0,0,0,1};
99        sty->scaleX = sty->scaleY = 100;
100        sty->tracking = sty->angle = 0;
101        sty->outlineRadius = 1.5;
102        sty->shadowDist = 2;
103        sty->marginL = sty->marginR = sty->marginV = 20;
104        sty->weight = 1;
105        sty->italic = sty->underline = sty->strikeout = NO;
106        sty->alignH = kSubAlignmentCenter;
107        sty->alignV = kSubAlignmentBottom;
108        sty->borderStyle = kSubBorderStyleNormal;
109        sty->ex = [delegate completedStyleParsing:sty];
110        sty->delegate = delegate;
111        return sty;
112}
113
114-(SubStyle*)initWithDictionary:(NSDictionary *)s scriptVersion:(UInt8)version delegate:(SubRenderer*)delegate_
115{
116        if (self = [super init]) {
117                NSString *tmp;
118                delegate = delegate_;
119                NSString *sv;
120                               
121#define sv(fn, n) fn = [[s objectForKey: @""#n] retain]
122#define fv(fn, n) sv = [s objectForKey:@""#n]; fn = sv ? [sv floatValue] : 0.;
123#define iv(fn, n) fn = [[s objectForKey:@""#n] intValue]
124#define bv(fn, n) fn = [[s objectForKey:@""#n] intValue] != 0
125#define cv(fn, n) tmp = [s objectForKey:@""#n]; if (tmp) fn = ParseSSAColorString(tmp);
126               
127                sv(name, Name);
128                sv(fontname, Fontname);
129                fv(size, Fontsize);
130                cv(primaryColor, PrimaryColour);
131                cv(secondaryColor, SecondaryColour);
132                tmp = [s objectForKey:@"BackColour"];
133                if (tmp) outlineColor = shadowColor = ParseSSAColorString(tmp);
134                cv(outlineColor, OutlineColour);
135                cv(shadowColor, ShadowColour);
136                fv(weight, Bold);
137                bv(italic, Italic);
138                bv(underline, Underline);
139                bv(strikeout, Strikeout);
140                fv(scaleX, ScaleX);
141                fv(scaleY, ScaleY);
142                fv(tracking, Spacing);
143                fv(angle, Angle);
144                fv(outlineRadius, Outline);
145                fv(shadowDist, Shadow);
146                iv(marginL, MarginL);
147                iv(marginR, MarginR);
148                iv(marginV, MarginV);
149                iv(borderStyle, BorderStyle);
150               
151                if (!scaleX) scaleX = 100;
152                if (!scaleY) scaleY = 100;
153                if (weight == -1) weight = 1;
154
155                UInt8 align = [[s objectForKey:@"Alignment"] intValue];
156                if (version == kSubTypeSSA) align = SSA2ASSAlignment(align);
157               
158                ParseASSAlignment(align, &alignH, &alignV);
159               
160                platformSizeScale = 0;
161                ex = [delegate completedStyleParsing:self];
162        }
163       
164        return self;
165}
166
167static NSString *yes(int i) {return i ? @"yes" : @"no";}
168
169static NSString *ColorString(SubRGBAColor *c)
170{
171        return [NSString stringWithFormat:@"{R: %d G: %d B: %d A: %d}", (int)(c->red * 255),
172                                         (int)(c->green * 255), (int)(c->blue * 255), (int)(c->alpha * 255)];
173}
174
175-(NSString *)description
176{
177        static const NSString *alignHStr[] = {@"left", @"center", @"right"};
178        static const NSString *alignVStr[] = {@"bottom", @"middle", @"top"};
179        static const NSString *bstyle[] = {@"normal", @"box"};
180       
181        return [NSString stringWithFormat:@""
182                                         "SubStyle named \"%@\"\n"
183                                         "-Font: %f pt %@\n"
184                                         "-Primary color: %@\n"
185                                         "-Secondary color: %@\n"
186                                         "-Outline: %f px %@\n"
187                                         "-Shadow: %f px %@\n"
188                                         "-Margin: %d px left, %d px right, %d px vertical\n"
189                                         "-Bold: %@ Italic: %@ Underline: %@ Strikeout: %@\n"
190                                         "-Alignment: %@ %@\n"
191                                         "-Border style: %@\n"
192                                         "-Per-font scale: %f\n",
193                                         name, size, fontname, ColorString(&primaryColor),
194                                         ColorString(&secondaryColor), outlineRadius, ColorString(&outlineColor),
195                                         shadowDist, ColorString(&shadowColor), marginL, marginR, marginV,
196                                         yes(bold), yes(italic), yes(underline), yes(strikeout), alignHStr[alignH],
197                                         alignVStr[alignV], bstyle[borderStyle], platformSizeScale];
198}
199
200-(void)dealloc
201{
202        [name release];
203        [fontname release];
204        [delegate releaseStyleExtra:ex];
205        [super dealloc];
206}
207
208-(void)finalize
209{
210        [delegate releaseStyleExtra:ex];
211        [super finalize];
212}
213@end
214
215@implementation SubContext
216
217BOOL IsScriptASS(NSDictionary *headers)
218{       
219        return [[[headers objectForKey:@"ScriptType"] lowercaseString] isEqualToString:@"v4.00+"];
220}
221
222-(void)readHeaders
223{
224        scriptType = IsScriptASS(headers) ? kSubTypeASS : kSubTypeSSA;
225        collisions = [[headers objectForKey:@"Collisions"] isEqualToString:@"Reverse"] ? kSubCollisionsReverse : kSubCollisionsNormal;
226        wrapStyle = [[headers objectForKey:@"WrapStyle"] intValue];
227       
228        NSString *resXS = [headers objectForKey:@"PlayResX"], *resYS = [headers objectForKey:@"PlayResY"];
229       
230        if (resXS) resX = [resXS floatValue];
231        if (resYS) resY = [resYS floatValue];
232       
233        // obscure res rules copied from VSFilter
234        if ((!resXS && !resYS) || (!resX && !resY)) {
235                resX = 384; resY = 288;
236        } else if (!resYS) {
237                resY = (resX == 1280) ? 1024 : (resX / (4./3.));
238        } else if (!resXS) {
239                resX = (resY == 1024) ? 1280 : (resY * (4./3.));
240        }
241}
242
243-(SubContext*)initWithHeaders:(NSDictionary *)headers_ styles:(NSArray *)styles_ delegate:(SubRenderer*)delegate
244{
245        if (self = [super init]) {
246                headers = [headers_ retain];
247                [self readHeaders];
248               
249                [delegate completedHeaderParsing:self];
250               
251                styles = nil;
252                if (styles_) {
253                        int i, nstyles = [styles_ count];
254                        NSMutableDictionary *sdict = [[NSMutableDictionary alloc] initWithCapacity:nstyles];
255                       
256                        for (i=0; i < nstyles; i++) {
257                                NSDictionary *style = [styles_ objectAtIndex:i];
258                                [sdict setObject:[[[SubStyle alloc] initWithDictionary:style scriptVersion:scriptType delegate:delegate] autorelease]
259                                                                                                forKey:[style objectForKey:@"Name"]];
260                        }
261                       
262                        styles = sdict;
263                }
264               
265                defaultStyle = [styles objectForKey:@"Default"];
266                if (!defaultStyle) defaultStyle = [SubStyle defaultStyleWithDelegate:delegate];
267                [defaultStyle retain];
268               
269        }
270       
271        return self;
272}
273
274-(SubContext*)initWithNonSSAType:(UInt8)type delegate:(SubRenderer*)delegate
275{
276        if (self = [super init]) {
277                resX = 640;
278                resY = 480;
279                scriptType = type;
280                collisions = kSubCollisionsNormal;
281                wrapStyle = kSubLineWrapBottomWider;
282                styles = headers = nil;
283                [delegate completedHeaderParsing:self];
284
285                defaultStyle = [[SubStyle defaultStyleWithDelegate:delegate] retain];           
286        }
287       
288        return self;
289}
290
291-(void)dealloc
292{
293        [styles release];
294        [defaultStyle release];
295        [headers release];
296        [super dealloc];
297}
298
299-(SubStyle*)styleForName:(NSString *)name
300{
301        SubStyle *sty = [styles objectForKey:name];
302        return sty ? sty : defaultStyle;
303}
304@end
305
306@implementation SubRenderer
307-(void*)completedStyleParsing:(SubStyle*)s {return nil;}
308-(void)completedHeaderParsing:(SubContext*)sc {}
309-(void*)spanExtraFromRenderDiv:(SubRenderDiv*)div {return nil;}
310-(void*)cloneSpanExtra:(SubRenderSpan*)span {return span->ex;}
311-(void)spanChangedTag:(SSATagType)tag span:(SubRenderSpan*)span div:(SubRenderDiv*)div param:(void*)p {}
312-(void)releaseStyleExtra:(void*)ex {}
313-(void)releaseSpanExtra:(void*)ex {}
314-(float)aspectRatio {return 4./3.;}
315-(NSString*)describeSpanEx:(void*)ex {return @"";}
316@end
Note: See TracBrowser for help on using the repository browser.