Changeset 252942 in webkit


Ignore:
Timestamp:
Nov 29, 2019 8:30:05 AM (4 years ago)
Author:
Antti Koivisto
Message:

[LFC][IFC] Vector allocate LineBoxes and Display::Runs
https://bugs.webkit.org/show_bug.cgi?id=204699

Reviewed by Zalan Bujtas.

Also rename inlineRuns -> displayRuns to match the type.

  • layout/FormattingContextGeometry.cpp:

(WebCore::Layout::FormattingContext::Geometry::contentHeightForFormattingContextRoot const):

  • layout/RenderBlockFlowLineLayout.cpp:

(WebCore::Layout::RenderBlockFlowLineLayout::layout):

  • layout/Verification.cpp:

(WebCore::Layout::outputMismatchingSimpleLineInformationIfNeeded):
(WebCore::Layout::outputMismatchingComplexLineInformationIfNeeded):

  • layout/blockformatting/BlockFormattingContextGeometry.cpp:

(WebCore::Layout::BlockFormattingContext::Geometry::inFlowNonReplacedHeightAndMargin):

  • layout/blockformatting/BlockMarginCollapse.cpp:

(WebCore::Layout::BlockFormattingContext::MarginCollapse::marginsCollapseThrough const):

  • layout/displaytree/DisplayPainter.cpp:

(WebCore::Display::paintInlineContent):

  • layout/inlineformatting/InlineFormattingContext.cpp:

(WebCore::Layout::InlineFormattingContext::setDisplayBoxesForLine):
(WebCore::Layout::InlineFormattingContext::invalidateFormattingState):

  • layout/inlineformatting/InlineFormattingContextQuirks.cpp:

(WebCore::Layout::InlineFormattingContext::Quirks::lineDescentNeedsCollapsing const):

  • layout/inlineformatting/InlineFormattingState.h:

(WebCore::Layout::InlineFormattingState::displayRuns const):
(WebCore::Layout::InlineFormattingState::displayRuns):
(WebCore::Layout::InlineFormattingState::addLineBox):
(WebCore::Layout::InlineFormattingState::lineBoxForRun const):
(WebCore::Layout::InlineFormattingState::addDisplayRun):
(WebCore::Layout::InlineFormattingState::resetDisplayRuns):
(WebCore::Layout::InlineFormattingState::inlineRuns const): Deleted.
(WebCore::Layout::InlineFormattingState::inlineRuns): Deleted.
(WebCore::Layout::InlineFormattingState::addInlineRun): Deleted.
(WebCore::Layout::InlineFormattingState::resetInlineRuns): Deleted.

  • layout/inlineformatting/InlineLineBuilder.cpp:

(WebCore::Layout::LineBuilder::alignContentVertically):
(WebCore::Layout::LineBuilder::adjustBaselineAndLineHeight):

  • layout/layouttree/LayoutTreeBuilder.cpp:

(WebCore::Layout::outputInlineRuns):

Location:
trunk/Source/WebCore
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r252941 r252942  
     12019-11-29  Antti Koivisto  <antti@apple.com>
     2
     3        [LFC][IFC] Vector allocate LineBoxes and Display::Runs
     4        https://bugs.webkit.org/show_bug.cgi?id=204699
     5
     6        Reviewed by Zalan Bujtas.
     7
     8        Also rename inlineRuns -> displayRuns to match the type.
     9
     10        * layout/FormattingContextGeometry.cpp:
     11        (WebCore::Layout::FormattingContext::Geometry::contentHeightForFormattingContextRoot const):
     12        * layout/RenderBlockFlowLineLayout.cpp:
     13        (WebCore::Layout::RenderBlockFlowLineLayout::layout):
     14        * layout/Verification.cpp:
     15        (WebCore::Layout::outputMismatchingSimpleLineInformationIfNeeded):
     16        (WebCore::Layout::outputMismatchingComplexLineInformationIfNeeded):
     17        * layout/blockformatting/BlockFormattingContextGeometry.cpp:
     18        (WebCore::Layout::BlockFormattingContext::Geometry::inFlowNonReplacedHeightAndMargin):
     19        * layout/blockformatting/BlockMarginCollapse.cpp:
     20        (WebCore::Layout::BlockFormattingContext::MarginCollapse::marginsCollapseThrough const):
     21        * layout/displaytree/DisplayPainter.cpp:
     22        (WebCore::Display::paintInlineContent):
     23        * layout/inlineformatting/InlineFormattingContext.cpp:
     24        (WebCore::Layout::InlineFormattingContext::setDisplayBoxesForLine):
     25        (WebCore::Layout::InlineFormattingContext::invalidateFormattingState):
     26        * layout/inlineformatting/InlineFormattingContextQuirks.cpp:
     27        (WebCore::Layout::InlineFormattingContext::Quirks::lineDescentNeedsCollapsing const):
     28        * layout/inlineformatting/InlineFormattingState.h:
     29        (WebCore::Layout::InlineFormattingState::displayRuns const):
     30        (WebCore::Layout::InlineFormattingState::displayRuns):
     31        (WebCore::Layout::InlineFormattingState::addLineBox):
     32        (WebCore::Layout::InlineFormattingState::lineBoxForRun const):
     33        (WebCore::Layout::InlineFormattingState::addDisplayRun):
     34        (WebCore::Layout::InlineFormattingState::resetDisplayRuns):
     35        (WebCore::Layout::InlineFormattingState::inlineRuns const): Deleted.
     36        (WebCore::Layout::InlineFormattingState::inlineRuns): Deleted.
     37        (WebCore::Layout::InlineFormattingState::addInlineRun): Deleted.
     38        (WebCore::Layout::InlineFormattingState::resetInlineRuns): Deleted.
     39        * layout/inlineformatting/InlineLineBuilder.cpp:
     40        (WebCore::Layout::LineBuilder::alignContentVertically):
     41        (WebCore::Layout::LineBuilder::adjustBaselineAndLineHeight):
     42        * layout/layouttree/LayoutTreeBuilder.cpp:
     43        (WebCore::Layout::outputInlineRuns):
     44
    1452019-11-29  Zalan Bujtas  <zalan@apple.com>
    246
  • trunk/Source/WebCore/layout/FormattingContextGeometry.cpp

    r252862 r252942  
    135135        // Even empty containers generate one line.
    136136        ASSERT(!lineBoxes.isEmpty());
    137         top = lineBoxes.first()->logicalTop();
    138         bottom = lineBoxes.last()->logicalBottom();
     137        top = lineBoxes.first().logicalTop();
     138        bottom = lineBoxes.last().logicalBottom();
    139139    } else if (formattingRootContainer.establishesBlockFormattingContext() || formattingRootContainer.establishesTableFormattingContext() || formattingRootContainer.isDocumentBox()) {
    140140        if (formattingRootContainer.hasInFlowChild()) {
  • trunk/Source/WebCore/layout/RenderBlockFlowLineLayout.cpp

    r252912 r252942  
    8080
    8181    auto& lineBoxes = downcast<InlineFormattingState>(m_layoutState->establishedFormattingState(rootContainer)).lineBoxes();
    82     auto height = lineBoxes.last()->logicalBottom();
     82    auto height = lineBoxes.last().logicalBottom();
    8383
    8484    auto& displayBox = m_layoutState->displayBoxForLayoutBox(rootContainer);
  • trunk/Source/WebCore/layout/Verification.cpp

    r252487 r252942  
    7878    auto& inlineFormattingState = layoutState.establishedFormattingState(inlineFormattingRoot);
    7979    ASSERT(is<InlineFormattingState>(inlineFormattingState));
    80     auto& inlineRunList = downcast<InlineFormattingState>(inlineFormattingState).inlineRuns();
    81 
    82     if (inlineRunList.size() != lineLayoutData->runCount()) {
    83         stream << "Mismatching number of runs: simple runs(" << lineLayoutData->runCount() << ") inline runs(" << inlineRunList.size() << ")";
     80    auto& displayRuns = downcast<InlineFormattingState>(inlineFormattingState).displayRuns();
     81
     82    if (displayRuns.size() != lineLayoutData->runCount()) {
     83        stream << "Mismatching number of runs: simple runs(" << lineLayoutData->runCount() << ") inline runs(" << displayRuns.size() << ")";
    8484        stream.nextLine();
    8585        return true;
     
    8989    for (unsigned i = 0; i < lineLayoutData->runCount(); ++i) {
    9090        auto& simpleRun = lineLayoutData->runAt(i);
    91         auto& inlineRun = *inlineRunList[i];
    92 
    93         auto matchingRuns = areEssentiallyEqual(simpleRun.logicalLeft, inlineRun.logicalLeft()) && areEssentiallyEqual(simpleRun.logicalRight, inlineRun.logicalRight());
    94         if (matchingRuns && inlineRun.textContext()) {
    95             matchingRuns = simpleRun.start == inlineRun.textContext()->start() && simpleRun.end == inlineRun.textContext()->end();
     91        auto& displayRun = displayRuns[i];
     92
     93        auto matchingRuns = areEssentiallyEqual(simpleRun.logicalLeft, displayRun.logicalLeft()) && areEssentiallyEqual(simpleRun.logicalRight, displayRun.logicalRight());
     94        if (matchingRuns && displayRun.textContext()) {
     95            matchingRuns = simpleRun.start == displayRun.textContext()->start() && simpleRun.end == displayRun.textContext()->end();
    9696            // SLL handles strings in a more concatenated format <div>foo<br>bar</div> -> foo -> 0,3 bar -> 3,6 vs. 0,3 and 0,3
    9797            if (!matchingRuns)
    98                 matchingRuns = (simpleRun.end - simpleRun.start) == (inlineRun.textContext()->end() - inlineRun.textContext()->start());
     98                matchingRuns = (simpleRun.end - simpleRun.start) == (displayRun.textContext()->end() - displayRun.textContext()->start());
    9999        }
    100100        if (matchingRuns)
     
    103103        stream << "Mismatching: simple run(" << simpleRun.start << ", " << simpleRun.end << ") (" << simpleRun.logicalLeft << ", " << simpleRun.logicalRight << ")";
    104104        stream << " inline run";
    105         if (inlineRun.textContext())
    106             stream << " (" << inlineRun.textContext()->start() << ", " << inlineRun.textContext()->end() << ")";
    107         stream << " (" << inlineRun.logicalLeft() << ", " << inlineRun.logicalTop() << ") (" << inlineRun.logicalWidth() << "x" << inlineRun.logicalHeight() << ")";
     105        if (displayRun.textContext())
     106            stream << " (" << displayRun.textContext()->start() << ", " << displayRun.textContext()->end() << ")";
     107        stream << " (" << displayRun.logicalLeft() << ", " << displayRun.logicalTop() << ") (" << displayRun.logicalWidth() << "x" << displayRun.logicalHeight() << ")";
    108108        stream.nextLine();
    109109        mismatched = true;
     
    159159    auto& inlineFormattingState = layoutState.establishedFormattingState(inlineFormattingRoot);
    160160    ASSERT(is<InlineFormattingState>(inlineFormattingState));
    161     auto& inlineRunList = downcast<InlineFormattingState>(inlineFormattingState).inlineRuns();
     161    auto& displayRuns = downcast<InlineFormattingState>(inlineFormattingState).displayRuns();
    162162
    163163    // Collect inlineboxes.
     
    168168    unsigned runIndex = 0;
    169169
    170     if (inlineBoxes.size() != inlineRunList.size()) {
    171         stream << "Warning: mismatching number of runs: inlineboxes(" << inlineBoxes.size() << ") vs. inline runs(" << inlineRunList.size() << ")";
     170    if (inlineBoxes.size() != displayRuns.size()) {
     171        stream << "Warning: mismatching number of runs: inlineboxes(" << inlineBoxes.size() << ") vs. inline runs(" << displayRuns.size() << ")";
    172172        stream.nextLine();
    173173    }
    174174
    175     for (unsigned inlineBoxIndex = 0; inlineBoxIndex < inlineBoxes.size() && runIndex < inlineRunList.size(); ++inlineBoxIndex) {
    176         auto& inlineRun = *inlineRunList[runIndex];
     175    for (unsigned inlineBoxIndex = 0; inlineBoxIndex < inlineBoxes.size() && runIndex < displayRuns.size(); ++inlineBoxIndex) {
     176        auto& displayRun = displayRuns[runIndex];
    177177        auto* inlineBox = inlineBoxes[inlineBoxIndex];
    178178        auto* inlineTextBox = is<InlineTextBox>(inlineBox) ? downcast<InlineTextBox>(inlineBox) : nullptr;
    179         bool matchingRuns = inlineTextBox ? checkForMatchingTextRuns(inlineRun, *inlineTextBox) : matchingRuns = checkForMatchingNonTextRuns(inlineRun, *inlineBox);
     179        bool matchingRuns = inlineTextBox ? checkForMatchingTextRuns(displayRun, *inlineTextBox) : matchingRuns = checkForMatchingNonTextRuns(displayRun, *inlineBox);
    180180
    181181        if (!matchingRuns) {
     
    195195
    196196            stream << " inline run";
    197             if (inlineRun.textContext())
    198                 stream << " (" << inlineRun.textContext()->start() << ", " << inlineRun.textContext()->end() << ")";
    199             stream << " (" << inlineRun.logicalLeft() << ", " << inlineRun.logicalTop() << ") (" << inlineRun.logicalWidth() << "x" << inlineRun.logicalHeight() << ")";
     197            if (displayRun.textContext())
     198                stream << " (" << displayRun.textContext()->start() << ", " << displayRun.textContext()->end() << ")";
     199            stream << " (" << displayRun.logicalLeft() << ", " << displayRun.logicalTop() << ") (" << displayRun.logicalWidth() << "x" << displayRun.logicalHeight() << ")";
    200200            stream.nextLine();
    201201            mismatched = true;
  • trunk/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp

    r252862 r252942  
    7676            // Even empty containers generate one line.
    7777            ASSERT(!lineBoxes.isEmpty());
    78             return { lineBoxes.last()->logicalBottom() - borderAndPaddingTop, nonCollapsedMargin };
     78            return { lineBoxes.last().logicalBottom() - borderAndPaddingTop, nonCollapsedMargin };
    7979        }
    8080
  • trunk/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp

    r252189 r252942  
    397397                auto& formattingState = downcast<InlineFormattingState>(layoutState.establishedFormattingState(layoutContainer));
    398398                for (auto& lineBox : formattingState.lineBoxes()) {
    399                     if (!lineBox->isConsideredEmpty())
     399                    if (!lineBox.isConsideredEmpty())
    400400                        return false;
    401401                }
  • trunk/Source/WebCore/layout/displaytree/DisplayPainter.cpp

    r252905 r252942  
    113113static void paintInlineContent(GraphicsContext& context, const Box& rootAbsoluteDisplayBox, const Layout::InlineFormattingState& formattingState)
    114114{
    115     auto& inlineRuns = formattingState.inlineRuns();
    116     if (inlineRuns.isEmpty())
     115    auto& displayRuns = formattingState.displayRuns();
     116    if (displayRuns.isEmpty())
    117117        return;
    118118
    119     for (auto& run : inlineRuns) {
    120         if (auto& textContext = run->textContext()) {
    121             auto& style = run->style();
     119    for (auto& run : displayRuns) {
     120        if (auto& textContext = run.textContext()) {
     121            auto& style = run.style();
    122122            context.setStrokeColor(style.color());
    123123            context.setFillColor(style.color());
    124124
    125             auto logicalLeft = rootAbsoluteDisplayBox.left() + run->logicalLeft();
     125            auto logicalLeft = rootAbsoluteDisplayBox.left() + run.logicalLeft();
    126126            // FIXME: Add non-baseline align painting
    127             auto& lineBox = formattingState.lineBoxForRun(*run);
     127            auto& lineBox = formattingState.lineBoxForRun(run);
    128128            auto baselineOffset = rootAbsoluteDisplayBox.top() + lineBox.logicalTop() + lineBox.baselineOffset();
    129129            if (auto expansionContext = textContext->expansion())
     
    131131            else
    132132                context.drawText(style.fontCascade(), TextRun { textContext->content(), logicalLeft }, { logicalLeft, baselineOffset });
    133         } else if (auto* cachedImage = run->image()) {
    134             auto runAbsoluteRect = FloatRect { rootAbsoluteDisplayBox.left() + run->logicalLeft(), rootAbsoluteDisplayBox.top() + run->logicalTop(), run->logicalWidth(), run->logicalHeight() };
     133        } else if (auto* cachedImage = run.image()) {
     134            auto runAbsoluteRect = FloatRect { rootAbsoluteDisplayBox.left() + run.logicalLeft(), rootAbsoluteDisplayBox.top() + run.logicalTop(), run.logicalWidth(), run.logicalHeight() };
    135135            context.drawImage(*cachedImage->image(), runAbsoluteRect);
    136136        }
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp

    r252932 r252942  
    428428
    429429    auto lineIndex = formattingState.lineBoxes().size();
    430     formattingState.addLineBox(lineContent.lineBox);
     430    formattingState.addLineBox(LineBox { lineContent.lineBox });
    431431
    432432    // Compute box final geometry.
     
    442442        auto initiatesInlineRun = !lineRun.isContainerStart() && !lineRun.isContainerEnd() && !lineRun.isCollapsedToVisuallyEmpty();
    443443        if (initiatesInlineRun)
    444             formattingState.addInlineRun(makeUnique<Display::Run>(lineIndex, lineRun.layoutBox().style(), lineRun.logicalRect(), lineRun.textContext()));
     444            formattingState.addDisplayRun({ lineIndex, lineRun.layoutBox().style(), lineRun.logicalRect(), lineRun.textContext() });
    445445
    446446        if (lineRun.isForcedLineBreak()) {
     
    502502    // Find out what we need to invalidate. This is where we add some smarts to do partial line layout.
    503503    // For now let's just clear the runs.
    504     formattingState().resetInlineRuns();
     504    formattingState().resetDisplayRuns();
    505505    // FIXME: This is also where we would delete inline items if their content changed.
    506506}
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingContextQuirks.cpp

    r252865 r252942  
    6565                auto& formattingState = downcast<InlineFormattingState>(layoutState.establishedFormattingState(downcast<Container>(layoutBox)));
    6666                ASSERT(!formattingState.lineBoxes().isEmpty());
    67                 auto inlineBlockBaseline = formattingState.lineBoxes().last()->baseline();
     67                auto inlineBlockBaseline = formattingState.lineBoxes().last().baseline();
    6868                if (inlineBlockBaseline.descent())
    6969                    return false;
  • trunk/Source/WebCore/layout/inlineformatting/InlineFormattingState.h

    r252932 r252942  
    3838namespace Layout {
    3939
    40 // Temp
    4140using InlineItems = Vector<std::unique_ptr<InlineItem>, 30>;
    42 using InlineRuns = Vector<std::unique_ptr<Display::Run>, 10>;
    43 using LineBoxes = Vector<std::unique_ptr<LineBox>, 5>;
     41
    4442// InlineFormattingState holds the state for a particular inline formatting context tree.
    4543class InlineFormattingState : public FormattingState {
     
    5351    void addInlineItem(std::unique_ptr<InlineItem>&& inlineItem) { m_inlineItems.append(WTFMove(inlineItem)); }
    5452
    55     const InlineRuns& inlineRuns() const { return m_inlineRuns; }
    56     InlineRuns& inlineRuns() { return m_inlineRuns; }
    57     void addInlineRun(std::unique_ptr<Display::Run>&&);
    58     void resetInlineRuns();
     53    using DisplayRuns = Vector<Display::Run, 10>;
     54    using LineBoxes = Vector<LineBox, 5>;
     55
     56    const DisplayRuns& displayRuns() const { return m_displayRuns; }
     57    DisplayRuns& displayRuns() { return m_displayRuns; }
     58    void addDisplayRun(Display::Run&&);
     59    void resetDisplayRuns();
    5960
    6061    const LineBoxes& lineBoxes() const { return m_lineBoxes; }
    6162    LineBoxes& lineBoxes() { return m_lineBoxes; }
    62     void addLineBox(const LineBox& lineBox) { m_lineBoxes.append(makeUnique<LineBox>(lineBox)); }
     63    void addLineBox(LineBox&& lineBox) { m_lineBoxes.append(lineBox); }
    6364
    64     const LineBox& lineBoxForRun(const Display::Run& inlineRun) const { return *m_lineBoxes[inlineRun.lineIndex()]; }
     65    const LineBox& lineBoxForRun(const Display::Run& displayRun) const { return m_lineBoxes[displayRun.lineIndex()]; }
    6566
    6667private:
     68    // Cacheable input to line layout.
    6769    InlineItems m_inlineItems;
    68     InlineRuns m_inlineRuns;
     70
     71    // Line layout results
     72    DisplayRuns m_displayRuns;
    6973    LineBoxes m_lineBoxes;
    7074};
    7175
    72 inline void InlineFormattingState::addInlineRun(std::unique_ptr<Display::Run>&& displayRun)
     76inline void InlineFormattingState::addDisplayRun(Display::Run&& displayRun)
    7377{
    74     m_inlineRuns.append(WTFMove(displayRun));
     78    m_displayRuns.append(WTFMove(displayRun));
    7579}
    7680
    77 inline void InlineFormattingState::resetInlineRuns()
     81inline void InlineFormattingState::resetDisplayRuns()
    7882{
    79     m_inlineRuns.clear();
     83    m_displayRuns.clear();
    8084    // Resetting the runs means no more line boxes either.
    8185    m_lineBoxes.clear();
  • trunk/Source/WebCore/layout/inlineformatting/InlineLineBuilder.cpp

    r252941 r252942  
    263263                // Spec makes us generate at least one line -even if it is empty.
    264264                ASSERT(!formattingState.lineBoxes().isEmpty());
    265                 auto inlineBlockBaselineOffset = formattingState.lineBoxes().last()->baselineOffset();
     265                auto inlineBlockBaselineOffset = formattingState.lineBoxes().last().baselineOffset();
    266266                // The inline-block's baseline offset is relative to its content box. Let's convert it relative to the margin box.
    267267                //   inline-block
     
    596596                // Spec makes us generate at least one line -even if it is empty.
    597597                ASSERT(!formattingState.lineBoxes().isEmpty());
    598                 auto& lastLineBox = *formattingState.lineBoxes().last();
     598                auto& lastLineBox = formattingState.lineBoxes().last();
    599599                auto inlineBlockBaseline = lastLineBox.baseline();
    600600                auto beforeHeight = boxGeometry.marginBefore() + boxGeometry.borderTop() + boxGeometry.paddingTop().valueOr(0);
  • trunk/Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp

    r252920 r252942  
    312312{
    313313    auto& inlineFormattingState = downcast<InlineFormattingState>(layoutState.establishedFormattingState(inlineFormattingRoot));
    314     auto& inlineRuns = inlineFormattingState.inlineRuns();
     314    auto& displayRuns = inlineFormattingState.displayRuns();
    315315    auto& lineBoxes = inlineFormattingState.lineBoxes();
    316316
     
    322322    stream << "lines are -> ";
    323323    for (auto& lineBox : lineBoxes)
    324         stream << "[" << lineBox->logicalLeft() << "," << lineBox->logicalTop() << " " << lineBox->logicalWidth() << "x" << lineBox->logicalHeight() << "] ";
     324        stream << "[" << lineBox.logicalLeft() << "," << lineBox.logicalTop() << " " << lineBox.logicalWidth() << "x" << lineBox.logicalHeight() << "] ";
    325325    stream.nextLine();
    326326
    327     for (auto& inlineRun : inlineRuns) {
     327    for (auto& displayRun : displayRuns) {
    328328        unsigned printedCharacters = 0;
    329329        while (++printedCharacters <= depth * 2)
    330330            stream << " ";
    331331        stream << "  ";
    332         if (inlineRun->textContext())
     332        if (displayRun.textContext())
    333333            stream << "inline text box";
    334334        else
    335335            stream << "inline box";
    336         stream << " at (" << inlineRun->logicalLeft() << "," << inlineRun->logicalTop() << ") size " << inlineRun->logicalWidth() << "x" << inlineRun->logicalHeight();
    337         if (inlineRun->textContext())
    338             stream << " run(" << inlineRun->textContext()->start() << ", " << inlineRun->textContext()->end() << ")";
     336        stream << " at (" << displayRun.logicalLeft() << "," << displayRun.logicalTop() << ") size " << displayRun.logicalWidth() << "x" << displayRun.logicalHeight();
     337        if (displayRun.textContext())
     338            stream << " run(" << displayRun.textContext()->start() << ", " << displayRun.textContext()->end() << ")";
    339339        stream.nextLine();
    340340    }
Note: See TracChangeset for help on using the changeset viewer.