MCPcopy Create free account
hub / github.com/crosspoint-reader/crosspoint-reader / layoutAndExtractLines

Method layoutAndExtractLines

lib/Epub/Epub/ParsedText.cpp:466–534  ·  view source on GitHub ↗

Consumes data to minimize memory usage

Source from the content-addressed store, hash-verified

464}
465// Consumes data to minimize memory usage
466void ParsedText::layoutAndExtractLines(const GfxRenderer& renderer, const int fontId, const uint16_t viewportWidth,
467 const std::function<void(std::shared_ptr<TextBlock>)>& processLine,
468 const bool includeLastLine) {
469 if (words.empty()) {
470 return;
471 }
472
473 // Per-paragraph RTL auto-detection: only when CSS/HTML didn't explicitly set direction.
474 // Explicit dir="ltr" must be respected and not overridden by content heuristic.
475 if (!blockStyle.directionDefined && hasRtlWord) {
476 // Check the first few words for RTL letter codepoints (no heap allocation).
477 const size_t wordsToScan = std::min(words.size(), RTL_PARAGRAPH_PROBE_WORDS);
478 for (size_t i = 0; i < wordsToScan; ++i) {
479 if (BidiUtils::startsWithRtl(words[i].c_str(), BidiUtils::RTL_PARAGRAPH_PROBE_DEPTH)) {
480 blockStyle.isRtl = true;
481 break;
482 }
483 }
484 }
485
486 isNaturalAlign =
487 blockStyle.alignment == CssTextAlign::Justify ||
488 (blockStyle.isRtl ? blockStyle.alignment == CssTextAlign::Right : blockStyle.alignment == CssTextAlign::Left);
489
490 // Ensure SD card font glyph metrics are loaded before measuring word widths.
491 // For flash-based fonts isSdCardFont() returns false and this block is skipped
492 // entirely — no heap allocation. For SD card fonts this reads glyph metadata
493 // (advanceX only, no bitmaps) for all unique codepoints in this paragraph so
494 // that calculateWordWidths() can measure text without on-demand SD I/O.
495 if (renderer.isSdCardFont(fontId)) {
496 // Style mask: only ask the SD font to load advances for styles actually
497 // used in this paragraph. Style index is the low two bits (regular/bold/
498 // italic/bold-italic); the underline bit is irrelevant to advance metrics.
499 uint8_t styleMask = 0;
500 for (auto s : wordStyles) {
501 styleMask |= static_cast<uint8_t>(1u << (static_cast<uint8_t>(s) & 0x03));
502 }
503 if (styleMask == 0) styleMask = 0x01; // defensive: regular only
504 renderer.ensureSdCardFontReady(fontId, words, hyphenationEnabled, styleMask);
505 }
506
507 const int pageWidth = viewportWidth;
508 auto wordWidths = calculateWordWidths(renderer, fontId);
509
510 std::vector<size_t> lineBreakIndices;
511 if (hyphenationEnabled) {
512 // Use greedy layout that can split words mid-loop when a hyphenated prefix fits.
513 lineBreakIndices =
514 computeHyphenatedLineBreaks(renderer, fontId, pageWidth, wordWidths, wordContinues, wordNoSpaceBefore);
515 } else {
516 lineBreakIndices = computeLineBreaks(renderer, fontId, pageWidth, wordWidths, wordContinues, wordNoSpaceBefore);
517 }
518 const size_t lineCount = includeLastLine ? lineBreakIndices.size() : lineBreakIndices.size() - 1;
519
520 for (size_t i = 0; i < lineCount; ++i) {
521 extractLine(i, pageWidth, wordWidths, wordContinues, wordNoSpaceBefore, lineBreakIndices, processLine, renderer,
522 fontId);
523 }

Callers 2

characterDataMethod · 0.80
makePagesMethod · 0.80

Calls 6

startsWithRtlFunction · 0.85
isSdCardFontMethod · 0.80
ensureSdCardFontReadyMethod · 0.80
emptyMethod · 0.45
sizeMethod · 0.45
beginMethod · 0.45

Tested by

no test coverage detected