- (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];
}
}
Что тут интересно?
ОтветитьУдалитьЧто используются "лямбды" - aDone и anInit.
И что вообще говоря этот код выполняется АСИНХРОННО в контексте операции anOp.
Которую вообще говоря - могут прерывать - на этот счёт есть проверки [anOp isCacelled]