Changeset 1208

Show
Ignore:
Timestamp:
11/23/09 23:25:15 (4 months ago)
Author:
astrange
Message:

SSA: Implement vertical text properly and fix it being badly misplaced.
\an5 used a completely wrong origin calculation.
Also try to put rotated vertical text in vaguely the right place - this probably won't work outside this file.
Fixes the rest of [Mazui]_To_Aru_Kagaku_no_Railgun_-_07_[D0494691].mkv.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Subtitles/SubATSUIRenderer.m

    r1204 r1208  
    3030static float GetWinFontSizeScale(ATSFontRef font); 
    3131static void FindAllPossibleLineBreaks(TextBreakLocatorRef breakLocator, const unichar *uline, UniCharArrayOffset lineLen, unsigned char *breakOpportunities); 
     32static ATSUFontID GetFontIDForSSAName(NSString *name); 
    3233 
    3334#define declare_bitfield(name, bits) unsigned char name[bits / 8 + 1]; bzero(name, sizeof(name)); 
     
    4041        CGColorRef primaryColor, outlineColor, shadowColor; 
    4142        Float32 outlineRadius, shadowDist, scaleX, scaleY, primaryAlpha, outlineAlpha, angle, platformSizeScale, fontSize; 
    42         BOOL blurEdges
     43        BOOL blurEdges, vertical
    4344        ATSUFontID font; 
    44         ATSUVerticalCharacterType fontVertical; 
    4545} 
    4646-(SubATSUISpanEx*)initWithStyle:(ATSUStyle)style_ subStyle:(SubStyle*)sstyle colorSpace:(CGColorSpaceRef)cs; 
     
    8989 
    9090-(SubATSUISpanEx*)initWithStyle:(ATSUStyle)style_ subStyle:(SubStyle*)sstyle colorSpace:(CGColorSpaceRef)cs 
    91 
    92         ByteCount unused; 
    93          
     91{        
    9492        if (self = [super init]) { 
    9593                ATSUCreateAndCopyStyle(style_, &style); 
     
    107105                platformSizeScale = sstyle->platformSizeScale; 
    108106                fontSize = sstyle->size; 
    109                 ATSUGetAttribute(style, kATSUFontTag, sizeof(ATSUFontID), &font, &unused)
    110                 ATSUGetAttribute(style, kATSUVerticalCharacterTag, sizeof(ATSUVerticalCharacterType), &fontVertical, &unused); 
     107                vertical = sstyle->vertical
     108                font = GetFontIDForSSAName(sstyle->fontname); 
    111109        } 
    112110         
     
    132130        ret->fontSize = fontSize; 
    133131        ret->font = font; 
    134         ret->fontVertical = fontVertical; 
     132        ret->blurEdges = blurEdges; 
     133        ret->vertical = vertical; 
    135134         
    136135        return ret; 
     
    342341-(void*)completedStyleParsing:(SubStyle*)s 
    343342{ 
    344         const ATSUAttributeTag tags[] = {kATSUStyleRenderingOptionsTag, kATSUSizeTag, kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag, kATSUStyleStrikeThroughTag, kATSUFontTag, kATSUVerticalCharacterTag}; 
    345         const ByteCount          sizes[] = {sizeof(ATSStyleRenderingOptions), sizeof(Fixed), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID), sizeof(ATSUVerticalCharacterType)}; 
     343        const ATSUAttributeTag tags[] = {kATSUStyleRenderingOptionsTag, kATSUSizeTag, kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag, kATSUStyleStrikeThroughTag, kATSUFontTag}; 
     344        const ByteCount          sizes[] = {sizeof(ATSStyleRenderingOptions), sizeof(Fixed), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), sizeof(ATSUFontID)}; 
    346345         
    347346        NSString *fn = s->fontname; 
    348         ATSUVerticalCharacterType vertical = ParseFontVerticality(&fn) ? kATSUStronglyVertical : kATSUStronglyHorizontal; 
    349347        ATSUFontID font = GetFontIDForSSAName(fn); 
    350348        ATSFontRef fontRef = font; 
     
    354352        ATSUStyle style; 
    355353                 
    356         const ATSUAttributeValuePtr vals[] = {&opt, &size, &b, &i, &u, &st, &font, &vertical}; 
     354        const ATSUAttributeValuePtr vals[] = {&opt, &size, &b, &i, &u, &st, &font}; 
    357355         
    358356        if (!s->platformSizeScale) s->platformSizeScale = GetWinFontSizeScale(fontRef); 
     
    413411        Fixed fSize = FloatToFixed(spanEx->fontSize * spanEx->platformSizeScale * screenScale); 
    414412        SetATSUStyleOther(spanEx->style, kATSUFontTag, sizeof(ATSUFontID), &spanEx->font); 
    415         SetATSUStyleOther(spanEx->style, kATSUVerticalCharacterTag, sizeof(ATSUVerticalCharacterType), &spanEx->fontVertical); 
    416413        SetATSUStyleOther(spanEx->style, kATSUSizeTag, sizeof(Fixed), &fSize); 
    417414} 
     
    471468                        sv(); 
    472469                        oldFont = spanEx->font; 
    473                         spanEx->fontVertical = ParseFontVerticality(&sval) ? kATSUStronglyVertical : kATSUStronglyHorizontal
     470                        spanEx->vertical = ParseFontVerticality(&sval)
    474471                        spanEx->font = GetFontIDForSSAName(sval); 
    475472                        if (oldFont != spanEx->font) spanEx->platformSizeScale = GetWinFontSizeScale(spanEx->font); 
     
    695692} 
    696693 
    697 static void SetStyleSpanRuns(ATSUTextLayout layout, SubRenderDiv *div) 
     694static void MakeRunVertical(ATSUTextLayout layout, UniCharArrayOffset spanOffset, UniCharArrayOffset length) 
     695
     696        ATSUStyle style, vStyle; 
     697        ATSUVerticalCharacterType vertical = kATSUStronglyVertical; 
     698         
     699        ATSUGetRunStyle(layout, spanOffset, &style, NULL, NULL); 
     700        ATSUCreateAndCopyStyle(style, &vStyle); 
     701        SetATSUStyleOther(vStyle, kATSUVerticalCharacterTag, sizeof(vertical), &vertical); 
     702        ATSUSetRunStyle(layout, vStyle, spanOffset, length); 
     703        ATSUDisposeStyle(vStyle); 
     704
     705 
     706static void EnableVerticalForSpan(ATSUTextLayout layout, SubRenderDiv *div, const unichar *ubuffer, UniCharArrayOffset spanOffset, UniCharArrayOffset length) 
     707
     708        const unichar tategakiLowerBound = 0x02F1; // copied from http://source.winehq.org/source/dlls/gdi32/freetype.c 
     709        int runStart, runAboveBound, i; 
     710         
     711        runStart = spanOffset; 
     712        runAboveBound = ubuffer[spanOffset] >= tategakiLowerBound; 
     713         
     714        for (i = spanOffset+1; i < spanOffset + length; i++) { 
     715                int isAboveBound = ubuffer[i] >= tategakiLowerBound; 
     716                 
     717                if (isAboveBound != runAboveBound) { 
     718                        if (runAboveBound) 
     719                                MakeRunVertical(layout, runStart, i - runStart); 
     720                        runStart = i; 
     721                        isAboveBound = runAboveBound; 
     722                } 
     723        } 
     724         
     725        if (runAboveBound) 
     726                MakeRunVertical(layout, runStart, i - runStart); 
     727
     728 
     729static void SetStyleSpanRuns(ATSUTextLayout layout, SubRenderDiv *div, const unichar *ubuffer) 
    698730{ 
    699731        unsigned span_count = [div->spans count]; 
     
    702734        for (i = 0; i < span_count; i++) { 
    703735                SubRenderSpan *span = [div->spans objectAtIndex:i]; 
    704                 UniCharArrayOffset next = (i == span_count-1) ? [div->text length] : ((SubRenderSpan*)[div->spans objectAtIndex:i+1])->offset; 
    705                 ATSUSetRunStyle(layout, span_ex(span)->style, span->offset, next - span->offset); 
     736                UniCharArrayOffset next = (i == span_count-1) ? [div->text length] : ((SubRenderSpan*)[div->spans objectAtIndex:i+1])->offset, spanLen = next - span->offset; 
     737                SubATSUISpanEx *ex = span->ex; 
     738 
     739                ATSUSetRunStyle(layout, ex->style, span->offset, spanLen); 
     740                 
     741                if (ex->vertical) { 
     742                        EnableVerticalForSpan(layout, div, ubuffer, span->offset, spanLen); 
     743                } 
    706744        } 
    707745} 
     
    10521090                unsigned textLen = [div->text length]; 
    10531091                if (!textLen || ![div->spans count]) continue; 
    1054                 BOOL resetPens = NO
     1092                BOOL resetPens = NO, resetGState = NO
    10551093                NSData *ubufferData; 
    10561094                const unichar *ubuffer = STUnicodeForString(div->text, &ubufferData); 
     
    10621100                 
    10631101                //NSLog(@"%@", div); 
    1064                                 
     1102                 
    10651103                NSRect marginRect = NSMakeRect(div->marginL, div->marginV, context->resX - div->marginL - div->marginR, context->resY - div->marginV - div->marginV); 
    10661104                 
     
    10771115                 
    10781116                SetLayoutPositioning(layout, breakingWidth, div->alignH); 
    1079                 SetStyleSpanRuns(layout, div); 
     1117                SetStyleSpanRuns(layout, div, ubuffer); 
    10801118                 
    10811119                breakbuffer = FindLineBreaks(layout, div, breakLocator, breakbuffer, &breakCount, breakingWidth, ubuffer, textLen); 
     
    11141152                                case kSubAlignmentMiddle: 
    11151153                                        if (!centerPen || resetPens) { 
    1116                                                 penY = (FloatToFixed(NSMidY(marginRect)) / 2) + (imageHeight / 2)
     1154                                                penY = FloatToFixed(NSMidY(marginRect)) - (imageHeight / 2) + descent
    11171155                                        } else penY = centerPen; 
    11181156                                         
     
    11471185                } 
    11481186                 
    1149                 { 
    1150                         SubATSUISpanEx *firstspan = ((SubRenderSpan*)[div->spans objectAtIndex:0])->ex; 
     1187                SubATSUISpanEx *firstspan = ((SubRenderSpan*)[div->spans objectAtIndex:0])->ex; 
     1188 
     1189                // FIXME: we can only rotate an entire line at once 
     1190                if (firstspan->angle) { 
    11511191                        Fixed fangle = FloatToFixed(firstspan->angle); 
     1192                        SetATSULayoutOther(layout, kATSULineRotationTag, sizeof(Fixed), &fangle); 
    11521193                         
    1153                         SetATSULayoutOther(layout, kATSULineRotationTag, sizeof(Fixed), &fangle); 
     1194                        // FIXME: awful hack for SSA vertical text idiom 
     1195                        // instead it needs to rotate text by hand or actually fix ATSUI's rotation origin 
     1196                        if (firstspan->vertical &&  
     1197                                div->alignV == kSubAlignmentMiddle && div->alignH == kSubAlignmentCenter) { 
     1198                                CGContextSaveGState(c); 
     1199                                CGContextTranslateCTM(c, FixedToFloat(imageWidth)/2, FixedToFloat(imageWidth)/2); 
     1200                                resetGState = YES; 
     1201                        } 
    11541202                } 
    11551203                 
     
    11611209                 
    11621210                penY = DrawOneTextDiv(c, layout, div, breakc, penX, penY); 
     1211                 
     1212                if (resetGState) 
     1213                        CGContextRestoreGState(c); 
    11631214                 
    11641215                [ubufferData release]; 
  • trunk/Subtitles/SubContext.h

    r1140 r1208  
    4545        unsigned marginL, marginR, marginV; 
    4646        Float32 weight; // 0/1 = not bold/bold, > 1 is a font weight 
    47         BOOL italic, underline, strikeout
     47        BOOL italic, underline, strikeout, vertical
    4848        UInt8 alignH, alignV, borderStyle; 
    4949        __strong void* ex; 
  • trunk/Subtitles/SubContext.m

    r1206 r1208  
    8383        if ([*fontname characterAtIndex:0] == '@') { 
    8484                *fontname = [*fontname substringFromIndex:1]; 
    85                 //return YES; // XXX vertical 
     85                return YES; 
    8686        } 
    8787        return NO; 
     
    160160                ParseASSAlignment(align, &alignH, &alignV); 
    161161                 
     162                tmp = fontname; 
     163                vertical = ParseFontVerticality(&tmp); 
     164                if (vertical) 
     165                        fontname = [tmp retain]; 
     166                 
    162167                platformSizeScale = 0; 
    163168                ex = [delegate completedStyleParsing:self];