📄 bidi.cpp
字号:
UChar current = characters[firstSpace - 1]; if (!isCollapsibleSpace(current, lastText)) break; firstSpace--; } if (firstSpace == trailingSpaceRun->stop()) trailingSpaceRun = 0; else { TextDirection direction = style()->direction(); bool shouldReorder = trailingSpaceRun != (direction == LTR ? resolver.lastRun() : resolver.firstRun()); if (firstSpace != trailingSpaceRun->start()) { ETextAlign textAlign = style()->textAlign(); // If the trailing white space is at the right hand side of a left-aligned line, then computeHorizontalPositionsForLine() // does not care if trailingSpaceRun includes non-spaces at the beginning. In all other cases, trailingSpaceRun has to // contain only the spaces, either because we re-order them or because computeHorizontalPositionsForLine() needs to know // their width. bool shouldSeparateSpaces = textAlign != LEFT && textAlign != WEBKIT_LEFT && textAlign != TAAUTO || trailingSpaceRun->m_level % 2 || direction == RTL || shouldReorder; if (shouldSeparateSpaces) { BidiContext* baseContext = resolver.context(); while (BidiContext* parent = baseContext->parent()) baseContext = parent; BidiRun* newTrailingRun = new (renderArena()) BidiRun(firstSpace, trailingSpaceRun->m_stop, trailingSpaceRun->m_object, baseContext, OtherNeutral); trailingSpaceRun->m_stop = firstSpace; if (direction == LTR) resolver.addRun(newTrailingRun); else resolver.prependRun(newTrailingRun); trailingSpaceRun = newTrailingRun; shouldReorder = false; } } if (shouldReorder) { if (direction == LTR) { resolver.moveRunToEnd(trailingSpaceRun); trailingSpaceRun->m_level = 0; } else { resolver.moveRunToBeginning(trailingSpaceRun); trailingSpaceRun->m_level = 1; } } } } else trailingSpaceRun = 0; } // Now that the runs have been ordered, we create the line boxes. // At the same time we figure out where border/padding/margin should be applied for // inline flow boxes. RootInlineBox* lineBox = 0; if (resolver.runCount()) { lineBox = constructLine(resolver.runCount(), resolver.firstRun(), resolver.lastRun(), firstLine, !end.obj, end.obj && !end.pos ? end.obj : 0); if (lineBox) { lineBox->setEndsWithBreak(previousLineBrokeCleanly); // Now we position all of our text runs horizontally. computeHorizontalPositionsForLine(lineBox, firstLine, resolver.firstRun(), trailingSpaceRun, end.atEnd()); // Now position our text runs vertically. computeVerticalPositionsForLine(lineBox, resolver.firstRun());#if ENABLE(SVG) // Special SVG text layout code lineBox->computePerCharacterLayoutInformation();#endif#if PLATFORM(MAC) // Highlight acts as an overflow inflation. if (style()->highlight() != nullAtom) lineBox->addHighlightOverflow();#endif } } resolver.deleteRuns(); if (lineBox) { lineBox->setLineBreakInfo(end.obj, end.pos, resolver.status()); if (useRepaintBounds) { repaintTop = min(repaintTop, lineBox->topOverflow()); repaintBottom = max(repaintBottom, lineBox->bottomOverflow()); } } firstLine = false; newLine(clear); } if (m_floatingObjects && lastRootBox()) { if (lastFloat) { for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) { } m_floatingObjects->next(); } else m_floatingObjects->first(); for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) { if (f->m_bottom > lastHeight) lastRootBox()->floats().append(f->m_renderer); ASSERT(f->m_renderer == floats[floatIndex].object); // If a float's geometry has changed, give up on syncing with clean lines. if (floats[floatIndex].rect != IntRect(f->m_left, f->m_top, f->m_width, f->m_bottom - f->m_top)) checkForEndLineMatch = false; floatIndex++; } lastFloat = m_floatingObjects->last(); } lastHeight = height(); sNumMidpoints = 0; sCurrMidpoint = 0; resolver.setPosition(end); } if (endLine) { if (endLineMatched) { // Attach all the remaining lines, and then adjust their y-positions as needed. int delta = height() - endLineYPos; for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) { line->attachLine(); if (delta) { repaintTop = min(repaintTop, line->topOverflow() + min(delta, 0)); repaintBottom = max(repaintBottom, line->bottomOverflow() + max(delta, 0)); line->adjustPosition(0, delta); } if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) { Vector<RenderBox*>::iterator end = cleanLineFloats->end(); for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) { int floatTop = (*f)->y() - (*f)->marginTop(); insertFloatingObject(*f); setHeight(floatTop + delta); positionNewFloats(); } } } setHeight(lastRootBox()->blockHeight()); } else { // Delete all the remaining lines. InlineRunBox* line = endLine; RenderArena* arena = renderArena(); while (line) { repaintTop = min(repaintTop, line->topOverflow()); repaintBottom = max(repaintBottom, line->bottomOverflow()); InlineRunBox* next = line->nextLineBox(); line->deleteLine(arena); line = next; } } } if (m_floatingObjects && (checkForFloatsFromLastLine || positionNewFloats()) && lastRootBox()) { // In case we have a float on the last line, it might not be positioned up to now. // This has to be done before adding in the bottom border/padding, or the float will // include the padding incorrectly. -dwh if (lastFloat) { for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) { } m_floatingObjects->next(); } else m_floatingObjects->first(); for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) { if (f->m_bottom > lastHeight) lastRootBox()->floats().append(f->m_renderer); } lastFloat = m_floatingObjects->last(); } } sNumMidpoints = 0; sCurrMidpoint = 0; // Now add in the bottom border/padding. setHeight(height() + toAdd); // Always make sure this is at least our height. m_overflowHeight = max(height(), m_overflowHeight); // See if any lines spill out of the block. If so, we need to update our overflow width. checkLinesForOverflow(); if (!firstLineBox() && hasLineIfEmpty()) setHeight(height() + lineHeight(true, true)); // See if we have any lines that spill out of our block. If we do, then we will possibly need to // truncate text. if (hasTextOverflow) checkLinesForTextOverflow();}RootInlineBox* RenderBlock::determineStartPosition(bool& firstLine, bool& fullLayout, InlineBidiResolver& resolver, Vector<FloatWithRect>& floats, unsigned& numCleanFloats){ RootInlineBox* curr = 0; RootInlineBox* last = 0; bool dirtiedByFloat = false; if (!fullLayout) { size_t floatIndex = 0; for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) { if (Vector<RenderBox*>* cleanLineFloats = curr->floatsPtr()) { Vector<RenderBox*>::iterator end = cleanLineFloats->end(); for (Vector<RenderBox*>::iterator o = cleanLineFloats->begin(); o != end; ++o) { RenderBox* f = *o; IntSize newSize(f->width() + f->marginLeft() +f->marginRight(), f->height() + f->marginTop() + f->marginBottom()); ASSERT(floatIndex < floats.size()); if (floats[floatIndex].object != f) { // A new float has been inserted before this line or before its last known float. // Just do a full layout. fullLayout = true; break; } if (floats[floatIndex].rect.size() != newSize) { int floatTop = floats[floatIndex].rect.y(); curr->markDirty(); markLinesDirtyInVerticalRange(curr->blockHeight(), floatTop + max(floats[floatIndex].rect.height(), newSize.height())); floats[floatIndex].rect.setSize(newSize); dirtiedByFloat = true; } floatIndex++; } } if (dirtiedByFloat || fullLayout) break; } // Check if a new float has been inserted after the last known float. if (!curr && floatIndex < floats.size()) fullLayout = true; } if (fullLayout) { // Nuke all our lines. if (firstRootBox()) { RenderArena* arena = renderArena(); curr = firstRootBox(); while (curr) { RootInlineBox* next = curr->nextRootBox(); curr->deleteLine(arena); curr = next; } ASSERT(!firstLineBox() && !lastLineBox()); } } else { if (curr) { // We have a dirty line. if (RootInlineBox* prevRootBox = curr->prevRootBox()) { // We have a previous line. if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(prevRootBox->lineBreakObj())->textLength())) // The previous line didn't break cleanly or broke at a newline // that has been deleted, so treat it as dirty too. curr = prevRootBox; } } else { // No dirty lines were found. // If the last line didn't break cleanly, treat it as dirty. if (lastRootBox() && !lastRootBox()->endsWithBreak()) curr = lastRootBox(); } // If we have no dirty lines, then last is just the last root box. last = curr ? curr->prevRootBox() : lastRootBox(); } numCleanFloats = 0; if (!floats.isEmpty()) { int savedHeight = height(); // Restore floats from clean lines. RootInlineBox* line = firstRootBox(); while (line != curr) { if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) { Vector<RenderBox*>::iterator end = cleanLineFloats->end(); for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) { insertFloatingObject(*f); setHeight((*f)->y() - (*f)->marginTop()); positionNewFloats(); ASSERT(floats[numCleanFloats].object == *f); numCleanFloats++; } } line = line->nextRootBox(); } setHeight(savedHeight); } firstLine = !last; previousLineBrokeCleanly = !last || last->endsWithBreak(); RenderObject* startObj; int pos = 0; if (last) { setHeight(last->blockHeight()); startObj = last->lineBreakObj(); pos = last->lineBreakPos(); resolver.setStatus(last->lineBreakBidiStatus()); } else { bool ltr = style()->direction() == LTR #if ENABLE(SVG) || (style()->unicodeBidi() == UBNormal && isSVGText()) #endif ; BidiContext* context = new BidiContext(ltr ? 0 : 1, ltr ? LeftToRight : RightToLeft, style()->unicodeBidi() == Override); resolver.setLastStrongDir(context->dir()); resolver.setLastDir(context->dir()); resolver.setEorDir(context->dir()); resolver.setContext(context); startObj = bidiFirst(this, &resolver); } resolver.setPosition(InlineIterator(this, startObj, pos)); return curr;}RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus, int& yPos){ RootInlineBox* last = 0; if (!startLine) last = 0; else { for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) { if (curr->isDirty()) last = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -