пятница, 1 ноября 2013 г.

Ещё кусочек "голого" кода для CoreText

- (void) checkRendered: (IsPageDone) aDone forOperation: (NSOperation *) anOp initCursorIndex: (InitCursorIndex) anInit
{
    if (!myDoc)
        return;
    
    if (anOp || self.stopOnPageBreak) {
        if (myRunnedOp)
            return;
    }
    if (anOp)
        myRunnedOp = YES;
    __block NSAutoreleasePool* vPool = [[NSAutoreleasePool alloc] init];
    @try {
        __block int vPageNum;
        @synchronized (self) {
            if (!myPages)
                myPages = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
            
            vPageNum = CFArrayGetCount(myPages) - 1;
        }
        
        assert(myDoc);
        EVDParaIndex vIndex ([myDoc blockIterator], 0, 0);
        anInit(vIndex);
        __block EVDParaIndex vParaIndex (vIndex);
        
        __block EVDRenderedPage *vPageRenderingNow = nil;
        @try {
            if (vPageNum >= 0) {
                EVDRenderedPage *vPrevPage = (EVDRenderedPage *)CFArrayGetValueAtIndex(myPages, vPageNum);
                if ([vPrevPage RenderedTillEnd]) {
                    //vParaAdded = YES;
                    // - а иначе в ДПЭ в раздел "Воинская служба" в конце добавляется ПУСТАЯ СТРАНИЦА
                    
                    vParaIndex = EVDParaIndex (myDoc, vPrevPage.EndsWithPara);
//                    vParaIndex.rInnerCursors = vPrevPage.EndsWithPara.rInnerCursors;
                    //                vParaIndex = vPrevPage->myEndsWithPara;
                    //                    if (vParaIndex.rOffset == 0)
                    vParaIndex.rPara++;
                    assert(vParaIndex.rPara >= 0);
                    if (vParaIndex.rPara >= INT32_MAX - 100)
                        // - это последняя страница
                        return;
                }
                else {
                    vParaIndex = EVDParaIndex (myDoc, vPrevPage.StartsWithPara);
//                    vParaIndex.rInnerCursors = vPrevPage.StartsWithPara.rInnerCursors;
                    ASSIGN(vPageRenderingNow, vPrevPage);
                    assert(vParaIndex.rPara >= 0);
                    //                    if (vParaIndex.rOffset > 0)
                    //                        vParaIndex.rParaIndex.rPara++;
                }
                {
                    BOOL vDone = NO;
                    aDone(vPageRenderingNow, vParaIndex, vDone);
                    if (vDone)
                        return;
                }
            }
            
            __block BOOL vPageWasFound = NO;
            
            __block BOOL vParaAdded = NO;
            
            __block CGRect vRect;
            initRectForPage(myRenderedForRect, vRect);
            
            __block EVDParaIndex vPrevParaIndex = vParaIndex;
                        
            for (; (vParaIndex.block() != nil); vParaIndex.moveToNextBlock()) {
                id<IevdBlock> vBlock = [[vParaIndex.block() block] retain];
                @try {
                    if (vPageWasFound)
                        if (!vPageRenderingNow)
                            // - типа страница вся была заполнена
                            break;
                    
                    if ((vPageRenderingNow && vParaAdded) || (self.stopOnPageBreak && (vPageNum > 0))) {
                        if (vParaIndex.startsNewPage()) {
                            vParaAdded = NO;
                            [vPageRenderingNow setEndsWithPara: vPrevParaIndex forDoc: self.Doc];
                            DESTROY(vPageRenderingNow);
                            if (self.stopOnPageBreak) {
                                myRunnedOp = YES;
                                break;
                            }
                            initRectForPage(myRenderedForRect, vRect);
                        }
                    }
                    
                    __block EVDRenderContext vCtx (vParaIndex, vRect, vParaAdded);
                    
                    [vBlock render: vCtx : ^(EVDRenderedPara * aRenderedPara){
                        
                            if (anOp && [anOp isCancelled]) {
                                myRunnedOp = NO;
                                vCtx.SetNeedReturn();
                                return;
                            }
                            
                            if ([aRenderedPara frame] || vParaAdded)
                                // - не начинаем НОВУЮ страницу с ПУСТОГО параграфа
                                [self checkRenderedPage: vPageRenderingNow : vPageNum : anOp : vParaIndex : aDone : vPageWasFound];
                            
                        } : ^(){
                            // - тут закончилась страница
//                            if (vPageNum == 428)
//                                NSLog(@"%d", vPageNum);
                            [vPageRenderingNow setEndsWithPara: vParaIndex forDoc: self.Doc];
                            DESTROY(vPageRenderingNow);
                            initRectForPage(myRenderedForRect, vRect);
                            vParaAdded = NO;
                            if (vPageNum % 20 == 0) {
                                [vPool drain];
                                vPool = [[NSAutoreleasePool alloc] init];
                            }
                            if (anOp && [myDoc needCancelPagesCounterWithScale: myScale]) {
                                myRunnedOp = NO;
                                vCtx.SetNeedReturn();
                            }
                            else
                            if (vPageWasFound)
                                vCtx.rNeedBreak = YES;
                    
                    }];
                    
                    if (vCtx.NeedReturn())
                        return;
                    
                    vPrevParaIndex = vParaIndex;
                    
                }
                @finally {
                    DESTROY(vBlock);
                }
            } // for (; (vParaIndex.rParaIndex.block()
        }
        @finally {
            if (vPageRenderingNow) {
                [vPageRenderingNow setEndsWithPara: vParaIndex forDoc: self.Doc];
                // - записываем текущий конец незаконченной страницы
                if (!myRunnedOp &&
                    self.stopOnPageBreak &&
                    (vParaIndex.block() == nil))
                    myRunnedOp = YES;
                else
                if (!anOp || [anOp isCancelled])
                    [vPageRenderingNow dropRenderedTillEnd];
            }
            DESTROY(vPageRenderingNow);
            if ((anOp || self.isPart) /*&& ![anOp isCancelled]*/)
                [self save];
        }
    }
    @finally {
        [vPool drain];
        if (anOp && ![anOp isCancelled])
            [self.Doc pagesCounterDone];
    }
}

1 комментарий:

  1. Что тут интересно?
    Что используются "лямбды" - aDone и anInit.

    И что вообще говоря этот код выполняется АСИНХРОННО в контексте операции anOp.

    Которую вообще говоря - могут прерывать - на этот счёт есть проверки [anOp isCacelled]

    ОтветитьУдалить