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

Method extractLine

lib/Epub/Epub/ParsedText.cpp:825–1184  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

823}
824
825void ParsedText::extractLine(const size_t breakIndex, const int pageWidth, const std::vector<uint16_t>& wordWidths,
826 const std::vector<bool>& continuesVec, const std::vector<bool>& noSpaceBeforeVec,
827 const std::vector<size_t>& lineBreakIndices,
828 const std::function<void(std::shared_ptr<TextBlock>)>& processLine,
829 const GfxRenderer& renderer, const int fontId) {
830 const size_t lineBreak = lineBreakIndices[breakIndex];
831 const size_t lastBreakAt = breakIndex > 0 ? lineBreakIndices[breakIndex - 1] : 0;
832 const size_t lineWordCount = lineBreak - lastBreakAt;
833
834 const int firstLineIndent = resolveFirstLineIndent(breakIndex == 0, renderer, fontId);
835
836 // Build line data by moving from the original vectors using index range
837 std::vector<std::string> lineWords;
838 lineWords.reserve(lineWordCount);
839 std::vector<EpdFontFamily::Style> lineWordStyles;
840 lineWordStyles.reserve(lineWordCount);
841
842 for (size_t i = 0; i < lineWordCount; ++i) {
843 std::string word = std::move(words[lastBreakAt + i]);
844 if (containsSoftHyphen(word)) {
845 stripSoftHyphensInPlace(word);
846 }
847 lineWords.push_back(std::move(word));
848 lineWordStyles.push_back(wordStyles[lastBreakAt + i]);
849 }
850
851 // Calculate total word width for this line, count actual word gaps,
852 // and accumulate total natural gap widths (including space kerning adjustments).
853 int lineWordWidthSum = 0;
854 size_t actualGapCount = 0;
855 int totalNaturalGaps = 0;
856
857 for (size_t wordIdx = 0; wordIdx < lineWordCount; wordIdx++) {
858 lineWordWidthSum += wordWidths[lastBreakAt + wordIdx];
859 // Count gaps: each word after the first creates a gap, unless it's a continuation
860 if (wordIdx > 0 && noSpaceBeforeVec[lastBreakAt + wordIdx]) {
861 // Unicode break opportunity with no inserted Latin-style space. It is still
862 // a stretchable gap for justified CJK/Korean text.
863 actualGapCount++;
864 } else if (wordIdx > 0 && !continuesVec[lastBreakAt + wordIdx]) {
865 actualGapCount++;
866 totalNaturalGaps += renderer.getSpaceAdvance(fontId, lastCodepoint(lineWords[wordIdx - 1]),
867 firstCodepoint(lineWords[wordIdx]), lineWordStyles[wordIdx - 1]);
868 } else if (wordIdx > 0 && continuesVec[lastBreakAt + wordIdx]) {
869 // Non-breaking space tokens (" " with continues=true) are visible, stretchable spaces —
870 // count them as justifiable gaps so justifyExtra is distributed to them too.
871 if (lineWords[wordIdx] == " ") {
872 actualGapCount++;
873 }
874 // Cross-boundary kerning for continuation words (e.g. nonbreaking spaces, attached punctuation)
875 totalNaturalGaps += renderer.getKerning(fontId, lastCodepoint(lineWords[wordIdx - 1]),
876 firstCodepoint(lineWords[wordIdx]), lineWordStyles[wordIdx - 1]);
877 }
878 }
879
880 // Calculate spacing (account for indent reducing effective page width on first line)
881 const int effectivePageWidth = pageWidth - firstLineIndent;
882 const bool isLastLine = breakIndex == lineBreakIndices.size() - 1;

Callers

nothing calls this directly

Calls 12

containsSoftHyphenFunction · 0.85
stripSoftHyphensInPlaceFunction · 0.85
lastCodepointFunction · 0.85
firstCodepointFunction · 0.85
computeJustifyExtraFunction · 0.85
computeVisualWordOrderFunction · 0.85
push_backMethod · 0.80
getSpaceAdvanceMethod · 0.80
getKerningMethod · 0.45
sizeMethod · 0.45
clearMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected