📄 textoutputdev.cc
字号:
minBase = newMinBase; // look for words on the line below the current bottom edge of // the block newMaxBase = maxBase; for (baseIdx = pool->getBaseIdx(maxBase); baseIdx <= pool->getBaseIdx(maxBase + lineSpace); ++baseIdx) { word0 = NULL; word1 = pool->getPool(baseIdx); while (word1) { if (word1->base > maxBase && word1->base <= maxBase + lineSpace && ((rot == 0 || rot == 2) ? (word1->xMin < blk->xMax && word1->xMax > blk->xMin) : (word1->yMin < blk->yMax && word1->yMax > blk->yMin)) && fabs(word1->fontSize - fontSize) < maxBlockFontSizeDelta1 * fontSize) { word2 = word1; if (word0) { word0->next = word1->next; } else { pool->setPool(baseIdx, word1->next); } word1 = word1->next; word2->next = NULL; blk->addWord(word2); found = gTrue; newMaxBase = word2->base; } else { word0 = word1; word1 = word1->next; } } } maxBase = newMaxBase; // look for words that are on lines already in the block, and // that overlap the block horizontally for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); ++baseIdx) { word0 = NULL; word1 = pool->getPool(baseIdx); while (word1) { if (word1->base >= minBase - intraLineSpace && word1->base <= maxBase + intraLineSpace && ((rot == 0 || rot == 2) ? (word1->xMin < blk->xMax + colSpace1 && word1->xMax > blk->xMin - colSpace1) : (word1->yMin < blk->yMax + colSpace1 && word1->yMax > blk->yMin - colSpace1)) && fabs(word1->fontSize - fontSize) < maxBlockFontSizeDelta2 * fontSize) { word2 = word1; if (word0) { word0->next = word1->next; } else { pool->setPool(baseIdx, word1->next); } word1 = word1->next; word2->next = NULL; blk->addWord(word2); found = gTrue; } else { word0 = word1; word1 = word1->next; } } } // only check for outlying words (the next two chunks of code) // if we didn't find anything else if (found) { continue; } // scan down the left side of the block, looking for words // that are near (but not overlapping) the block; if there are // three or fewer, add them to the block n = 0; for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); ++baseIdx) { word1 = pool->getPool(baseIdx); while (word1) { if (word1->base >= minBase - intraLineSpace && word1->base <= maxBase + intraLineSpace && ((rot == 0 || rot == 2) ? (word1->xMax <= blk->xMin && word1->xMax > blk->xMin - colSpace2) : (word1->yMax <= blk->yMin && word1->yMax > blk->yMin - colSpace2)) && fabs(word1->fontSize - fontSize) < maxBlockFontSizeDelta3 * fontSize) { ++n; break; } word1 = word1->next; } } if (n > 0 && n <= 3) { for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); ++baseIdx) { word0 = NULL; word1 = pool->getPool(baseIdx); while (word1) { if (word1->base >= minBase - intraLineSpace && word1->base <= maxBase + intraLineSpace && ((rot == 0 || rot == 2) ? (word1->xMax <= blk->xMin && word1->xMax > blk->xMin - colSpace2) : (word1->yMax <= blk->yMin && word1->yMax > blk->yMin - colSpace2)) && fabs(word1->fontSize - fontSize) < maxBlockFontSizeDelta3 * fontSize) { word2 = word1; if (word0) { word0->next = word1->next; } else { pool->setPool(baseIdx, word1->next); } word1 = word1->next; word2->next = NULL; blk->addWord(word2); if (word2->base < minBase) { minBase = word2->base; } else if (word2->base > maxBase) { maxBase = word2->base; } found = gTrue; break; } else { word0 = word1; word1 = word1->next; } } } } // scan down the right side of the block, looking for words // that are near (but not overlapping) the block; if there are // three or fewer, add them to the block n = 0; for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); ++baseIdx) { word1 = pool->getPool(baseIdx); while (word1) { if (word1->base >= minBase - intraLineSpace && word1->base <= maxBase + intraLineSpace && ((rot == 0 || rot == 2) ? (word1->xMin >= blk->xMax && word1->xMin < blk->xMax + colSpace2) : (word1->yMin >= blk->yMax && word1->yMin < blk->yMax + colSpace2)) && fabs(word1->fontSize - fontSize) < maxBlockFontSizeDelta3 * fontSize) { ++n; break; } word1 = word1->next; } } if (n > 0 && n <= 3) { for (baseIdx = pool->getBaseIdx(minBase - intraLineSpace); baseIdx <= pool->getBaseIdx(maxBase + intraLineSpace); ++baseIdx) { word0 = NULL; word1 = pool->getPool(baseIdx); while (word1) { if (word1->base >= minBase - intraLineSpace && word1->base <= maxBase + intraLineSpace && ((rot == 0 || rot == 2) ? (word1->xMin >= blk->xMax && word1->xMin < blk->xMax + colSpace2) : (word1->yMin >= blk->yMax && word1->yMin < blk->yMax + colSpace2)) && fabs(word1->fontSize - fontSize) < maxBlockFontSizeDelta3 * fontSize) { word2 = word1; if (word0) { word0->next = word1->next; } else { pool->setPool(baseIdx, word1->next); } word1 = word1->next; word2->next = NULL; blk->addWord(word2); if (word2->base < minBase) { minBase = word2->base; } else if (word2->base > maxBase) { maxBase = word2->base; } found = gTrue; break; } else { word0 = word1; word1 = word1->next; } } } } } while (found); //~ need to compute the primary writing mode (horiz/vert) in //~ addition to primary rotation // coalesce the block, and add it to the list blk->coalesce(uMap); if (lastBlk) { lastBlk->next = blk; } else { blkList = blk; } lastBlk = blk; count[rot] += blk->charCount; if (primaryRot < 0 || count[rot] > count[primaryRot]) { primaryRot = rot; } ++nBlocks; } }#if 0 // for debugging printf("*** rotation ***\n"); for (rot = 0; rot < 4; ++rot) { printf(" %d: %6d\n", rot, count[rot]); } printf(" primary rot = %d\n", primaryRot); printf("\n");#endif#if 0 // for debugging printf("*** blocks ***\n"); for (blk = blkList; blk; blk = blk->next) { printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f\n", blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax); for (line = blk->lines; line; line = line->next) { printf(" line: x=%.2f..%.2f y=%.2f..%.2f base=%.2f\n", line->xMin, line->xMax, line->yMin, line->yMax, line->base); for (word0 = line->words; word0; word0 = word0->next) { printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", word0->xMin, word0->xMax, word0->yMin, word0->yMax, word0->base, word0->fontSize, word0->spaceAfter); for (i = 0; i < word0->len; ++i) { fputc(word0->text[i] & 0xff, stdout); } printf("'\n"); } } } printf("\n");#endif // determine the primary direction lrCount = 0; for (blk = blkList; blk; blk = blk->next) { for (line = blk->lines; line; line = line->next) { for (word0 = line->words; word0; word0 = word0->next) { for (i = 0; i < word0->len; ++i) { if (unicodeTypeL(word0->text[i])) { ++lrCount; } else if (unicodeTypeR(word0->text[i])) { --lrCount; } } } } } primaryLR = lrCount >= 0;#if 0 // for debugging printf("*** direction ***\n"); printf("lrCount = %d\n", lrCount); printf("primaryLR = %d\n", primaryLR);#endif //----- column assignment // sort blocks into xy order for column assignment blocks = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *)); for (blk = blkList, i = 0; blk; blk = blk->next, ++i) { blocks[i] = blk; } qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpXYPrimaryRot); // column assignment for (i = 0; i < nBlocks; ++i) { blk0 = blocks[i]; col1 = 0; for (j = 0; j < i; ++j) { blk1 = blocks[j]; col2 = 0; // make gcc happy switch (primaryRot) { case 0: if (blk0->xMin > blk1->xMax) { col2 = blk1->col + blk1->nColumns + 3; } else if (blk1->xMax == blk1->xMin) { col2 = blk1->col; } else { col2 = blk1->col + (int)(((blk0->xMin - blk1->xMin) / (blk1->xMax - blk1->xMin)) * blk1->nColumns); } break; case 1: if (blk0->yMin > blk1->yMax) { col2 = blk1->col + blk1->nColumns + 3; } else if (blk1->yMax == blk1->yMin) { col2 = blk1->col; } else { col2 = blk1->col + (int)(((blk0->yMin - blk1->yMin) / (blk1->yMax - blk1->yMin)) * blk1->nColumns); } break; case 2: if (blk0->xMax < blk1->xMin) { col2 = blk1->col + blk1->nColumns + 3; } else if (blk1->xMin == blk1->xMax) { col2 = blk1->col; } else { col2 = blk1->col + (int)(((blk0->xMax - blk1->xMax) / (blk1->xMin - blk1->xMax)) * blk1->nColumns); } break; case 3: if (blk0->yMax < blk1->yMin) { col2 = blk1->col + blk1->nColumns + 3; } else if (blk1->yMin == blk1->yMax) { col2 = blk1->col; } else { col2 = blk1->col + (int)(((blk0->yMax - blk1->yMax) / (blk1->yMin - blk1->yMax)) * blk1->nColumns); } break; } if (col2 > col1) { col1 = col2; } } blk0->col = col1; for (line = blk0->lines; line; line = line->next) { for (j = 0; j <= line->len; ++j) { line->col[j] += col1; } } }#if 0 // for debugging printf("*** blocks, after column assignment ***\n"); for (blk = blkList; blk; blk = blk->next) { printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f col=%d nCols=%d\n", blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, blk->col, blk->nColumns); for (line = blk->lines; line; line = line->next) { printf(" line:\n"); for (word0 = line->words; word0; word0 = word0->next) { printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", word0->xMin, word0->xMax, word0->yMin, word0->yMax, word0->base, word0->fontSize, word0->spaceAfter); for (i = 0; i < word0->len; ++i) { fputc(word0->text[i] & 0xff, stdout); } printf("'\n"); } } } printf("\n");#endif //----- reading order sort // sort blocks into yx order (in preparation for reading order sort) qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpYXPrimaryRot); // compute space on left and right sides of each block for (i = 0; i < nBlocks; ++i) { blk0 = blocks[i]; for (j = 0; j < nBlocks; ++j) { blk1 = blocks[j]; if (blk1 != blk0) { blk0->updatePriMinMax(blk1); } } }#if 0 // for debugging printf("*** blocks, after yx sort ***\n"); for (i = 0; i < nBlocks; ++i) { blk = blocks[i]; printf("block: rot=%d x=%.2f..%.2f y=%.2f..%.2f space=%.2f..%.2f\n", blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, blk->priMin, blk->priMax); for (line = blk->lines; line; line = line->next) { printf(" line:\n"); for (word0 = line->words; word0; word0 = word0->next) { printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=%d: '", word0->xMin, word0->xMax, word0->yMin, word0->yMax, word0->base, word0->fontSize, word0->spaceAfter); for (j = 0; j < word0->len; ++j) { fputc(word0->text[j] & 0xff, stdout); } printf("'\n"); } } } printf("\n");#endif // build the flows //~ this needs to be adjusted for writing mode (vertical text) //~ this also needs to account for right-to-left column ordering blkArray = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *)); memcpy(blkArray, blocks, nBlocks * sizeof(TextBlock *)); flows = lastFlow = NULL; firstBlkIdx = 0; nBlocksLeft = nBlocks; while (nBlocksLeft > 0) { // find the upper-left-most block for (; !blkArray[firstBlkIdx]; ++firstBlkIdx) ; i = firstBlkIdx; blk = blkArray[i]; for (j = firstBlkIdx + 1; j < nBlocks; ++j) { blk1 = blkArray[j]; if (blk1) { if (blk && blk->secondaryDelta(blk1) > 0) { break; } if (blk1->primaryCmp(blk) < 0) { i = j; blk = blk1; } } } blkArray[i] = NULL; --nBlocksLeft; blk->next = NULL; // create a new flow, starting with the upper-left-most block flow = new TextFlow(this, blk); if (lastFlow) { lastFlow->next = flow; } else { flows = flow; } lastFlow = flow; fontSize = blk->lines->words->fontSize; // push the upper-left-most block on the stack blk->stackNext = NULL; blkStack = blk; // find the other blocks in this flow while (blkStack) { // find the upper-left-most block under (but within // maxBlockSpacing of) the top block on the stack blkSpace = maxBlockSpacing * blkStack->lines->words->fontSize; blk = NULL; i = -1; for (j = firstBlkIdx; j < nBlocks; ++j) { blk1 = blkArray[j]; if (blk1) { if (blkStack->secondaryDelta(blk1) > blkSpace) { break; } if (blk && blk->secondaryDelta(blk1) > 0) { break; } if (blk1->isBelow(blkStack) && (!blk || blk1->primaryCmp(blk) < 0)) { i = j; blk = blk1; } } } // if a suitable block was found, add it to the flow and push it // onto the stack if (blk && flow->blockFits(blk, blkStack)) { blkArray[i] = NULL; --nBlocksLeft; blk->next = NULL; flow->addBlock(blk); fontSize = blk->lines->words->fontSize; blk->stackNext = blkStack; blkStack = blk; // otherwise (if there is no block under the top block or the // block is not suitable), pop the stack } else { blkStack = blkStack->stackNext; } } } gfree(blkArray);#if 0 // for debugging printf("*** flows ***\n"); for (flow = flows; flow; flow = flow->next) { printf("flow: x=%.2f..%.2f y=%.2f..%.2f pri:%.2f..%.2f\n", flow->xMin, flow->xMax, flow->yMin, flow->yMax, flow->priMin, flow->priMax); for (blk = flow->blocks; blk; blk = blk->next) { printf(" block: rot=%d x=%.2f..%.2f y=%.2f..%.2f pri=%.2f..%.2f\n", blk->rot, blk->xMin, blk->xMax, blk->yMin, blk->yMax, blk->priMin, blk->priMax); for (line = blk->lines; line; line = line->next) { printf(" line:\n"); for (word0 = line->words; word0; word0 = word0->next) { printf(" word: x=%.2f..%.2f y=%.2f..%.2f base=%.2f fontSize=%.2f space=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -