📄 render_line.cpp
字号:
m_firstChild = child->nextOnLine();
if (child == m_lastChild)
m_lastChild = child->prevOnLine();
if (child->nextOnLine())
child->nextOnLine()->setPrevOnLine(child->prevOnLine());
if (child->prevOnLine())
child->prevOnLine()->setNextOnLine(child->nextOnLine());
child->setParent(0);
}
void InlineFlowBox::deleteLine(RenderArena* arena)
{
InlineBox* child = m_firstChild;
InlineBox* next = 0;
while (child) {
next = child->nextOnLine();
child->deleteLine(arena);
child = next;
}
static_cast<RenderFlow*>(m_object)->removeLineBox(this);
detach(arena);
}
void InlineFlowBox::extractLine()
{
if (!m_extracted)
static_cast<RenderFlow*>(m_object)->extractLineBox(this);
for (InlineBox* child = m_firstChild; child; child = child->nextOnLine())
child->extractLine();
}
void InlineFlowBox::attachLine()
{
if (m_extracted)
static_cast<RenderFlow*>(m_object)->attachLineBox(this);
for (InlineBox* child = m_firstChild; child; child = child->nextOnLine())
child->attachLine();
}
void InlineFlowBox::adjustPosition(int dx, int dy)
{
InlineRunBox::adjustPosition(dx, dy);
for (InlineBox* child = m_firstChild; child; child = child->nextOnLine())
child->adjustPosition(dx, dy);
}
bool InlineFlowBox::onEndChain(RenderObject* endObject)
{
if (!endObject)
return false;
if (endObject == object())
return true;
RenderObject* curr = endObject;
RenderObject* parent = curr->parent();
while (parent && !parent->isRenderBlock()) {
if (parent->lastChild() != curr)
return false;
curr = parent;
parent = curr->parent();
}
return true;
}
void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, RenderObject* endObject)
{
// All boxes start off open. They will not apply any margins/border/padding on
// any side.
bool includeLeftEdge = false;
bool includeRightEdge = false;
RenderFlow* flow = static_cast<RenderFlow*>(object());
if (!flow->firstChild())
includeLeftEdge = includeRightEdge = true; // Empty inlines never split across lines.
else if (parent()) { // The root inline box never has borders/margins/padding.
bool ltr = flow->style()->direction() == LTR;
// Check to see if all initial lines are unconstructed. If so, then
// we know the inline began on this line.
if (!flow->firstLineBox()->isConstructed()) {
if (ltr && flow->firstLineBox() == this)
includeLeftEdge = true;
else if (!ltr && flow->lastLineBox() == this)
includeRightEdge = true;
}
// In order to determine if the inline ends on this line, we check three things:
// (1) If we are the last line and we don't have a continuation(), then we can
// close up.
// (2) If the last line box for the flow has an object following it on the line (ltr,
// reverse for rtl), then the inline has closed.
// (3) The line may end on the inline. If we are the last child (climbing up
// the end object's chain), then we just closed as well.
if (!flow->lastLineBox()->isConstructed()) {
if (ltr) {
if (!nextLineBox() &&
((lastLine && !object()->continuation()) || nextOnLineExists()
|| onEndChain(endObject)))
includeRightEdge = true;
}
else {
if ((!prevLineBox() || !prevLineBox()->isConstructed()) &&
((lastLine && !object()->continuation()) ||
prevOnLineExists() || onEndChain(endObject)))
includeLeftEdge = true;
}
}
}
setEdges(includeLeftEdge, includeRightEdge);
// Recur into our children.
for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
if (currChild->isInlineFlowBox()) {
InlineFlowBox* currFlow = static_cast<InlineFlowBox*>(currChild);
currFlow->determineSpacingForFlowBoxes(lastLine, endObject);
}
}
}
int InlineFlowBox::placeBoxesHorizontally(int x, int& leftPosition, int& rightPosition)
{
// Set our x position.
setXPos(x);
leftPosition = kMin(x, leftPosition);
int startX = x;
x += borderLeft() + paddingLeft();
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->object()->isText()) {
InlineTextBox* text = static_cast<InlineTextBox*>(curr);
text->setXPos(x);
leftPosition = kMin(x, leftPosition);
rightPosition = kMax(x + text->width(), rightPosition);
x += text->width();
}
else {
if (curr->object()->isPositioned()) {
if (curr->object()->parent()->style()->direction() == LTR)
curr->setXPos(x);
else
// Our offset that we cache needs to be from the edge of the right border box and
// not the left border box. We have to subtract |x| from the width of the block
// (which can be obtained from the root line box).
curr->setXPos(root()->object()->width()-x);
continue; // The positioned object has no effect on the width.
}
if (curr->object()->isInlineFlow()) {
InlineFlowBox* flow = static_cast<InlineFlowBox*>(curr);
if (curr->object()->isCompact()) {
int ignoredX = x;
flow->placeBoxesHorizontally(ignoredX, leftPosition, rightPosition);
}
else {
x += flow->marginLeft();
x = flow->placeBoxesHorizontally(x, leftPosition, rightPosition);
x += flow->marginRight();
}
}
else if (!curr->object()->isCompact()) {
x += curr->object()->marginLeft();
curr->setXPos(x);
leftPosition = kMin(x, leftPosition);
rightPosition = kMax(x + curr->width(), rightPosition);
x += curr->width() + curr->object()->marginRight();
}
}
}
x += borderRight() + paddingRight();
setWidth(x-startX);
rightPosition = kMax(xPos() + width(), rightPosition);
return x;
}
void InlineFlowBox::verticallyAlignBoxes(int& heightOfBlock)
{
int maxPositionTop = 0;
int maxPositionBottom = 0;
int maxAscent = 0;
int maxDescent = 0;
// Figure out if we're in strict mode. Note that we can't simply use !style()->htmlHacks(),
// because that would match almost strict mode as well.
RenderObject* curr = object();
while (curr && !curr->element())
curr = curr->container();
bool strictMode = (curr && curr->document()->inStrictMode());
computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
if (maxAscent + maxDescent < kMax(maxPositionTop, maxPositionBottom))
adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
int maxHeight = maxAscent + maxDescent;
int topPosition = heightOfBlock;
int bottomPosition = heightOfBlock;
placeBoxesVertically(heightOfBlock, maxHeight, maxAscent, strictMode, topPosition, bottomPosition);
setVerticalOverflowPositions(topPosition, bottomPosition);
// Shrink boxes with no text children in quirks and almost strict mode.
if (!strictMode)
shrinkBoxesWithNoTextChildren(topPosition, bottomPosition);
heightOfBlock += maxHeight;
}
void InlineFlowBox::adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
int maxPositionTop, int maxPositionBottom)
{
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
// The computed lineheight needs to be extended for the
// positioned elements
if (curr->object()->isPositioned())
continue; // Positioned placeholders don't affect calculations.
if (curr->yPos() == PositionTop || curr->yPos() == PositionBottom) {
if (curr->yPos() == PositionTop) {
if (maxAscent + maxDescent < curr->height())
maxDescent = curr->height() - maxAscent;
}
else {
if (maxAscent + maxDescent < curr->height())
maxAscent = curr->height() - maxDescent;
}
if (maxAscent + maxDescent >= kMax(maxPositionTop, maxPositionBottom))
break;
}
if (curr->isInlineFlowBox())
static_cast<InlineFlowBox*>(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
}
}
void InlineFlowBox::computeLogicalBoxHeights(int& maxPositionTop, int& maxPositionBottom,
int& maxAscent, int& maxDescent, bool strictMode)
{
if (isRootInlineBox()) {
// Examine our root box.
setHeight(object()->lineHeight(m_firstLine, true));
bool isTableCell = object()->isTableCell();
if (isTableCell) {
RenderTableCell* tableCell = static_cast<RenderTableCell*>(object());
setBaseline(tableCell->RenderBlock::baselinePosition(m_firstLine, true));
}
else
setBaseline(object()->baselinePosition(m_firstLine, true));
if (hasTextChildren() || strictMode) {
int ascent = baseline();
int descent = height() - ascent;
if (maxAscent < ascent)
maxAscent = ascent;
if (maxDescent < descent)
maxDescent = descent;
}
}
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->object()->isPositioned())
continue; // Positioned placeholders don't affect calculations.
curr->setHeight(curr->object()->lineHeight(m_firstLine));
curr->setBaseline(curr->object()->baselinePosition(m_firstLine));
curr->setYPos(curr->object()->verticalPositionHint(m_firstLine));
if (curr->yPos() == PositionTop) {
if (maxPositionTop < curr->height())
maxPositionTop = curr->height();
}
else if (curr->yPos() == PositionBottom) {
if (maxPositionBottom < curr->height())
maxPositionBottom = curr->height();
}
else if (curr->hasTextChildren() || strictMode) {
int ascent = curr->baseline() - curr->yPos();
int descent = curr->height() - ascent;
if (maxAscent < ascent)
maxAscent = ascent;
if (maxDescent < descent)
maxDescent = descent;
}
if (curr->isInlineFlowBox())
static_cast<InlineFlowBox*>(curr)->computeLogicalBoxHeights(maxPositionTop, maxPositionBottom, maxAscent, maxDescent, strictMode);
}
}
void InlineFlowBox::placeBoxesVertically(int y, int maxHeight, int maxAscent, bool strictMode,
int& topPosition, int& bottomPosition)
{
if (isRootInlineBox())
setYPos(y + maxAscent - baseline());// Place our root box.
for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
if (curr->object()->isPositioned())
continue; // Positioned placeholders don't affect calculations.
// Adjust boxes to use their real box y/height and not the logical height (as dictated by
// line-height).
if (curr->isInlineFlowBox())
static_cast<InlineFlowBox*>(curr)->placeBoxesVertically(y, maxHeight, maxAscent, strictMode,
topPosition, bottomPosition);
bool childAffectsTopBottomPos = true;
if (curr->yPos() == PositionTop)
curr->setYPos(y);
else if (curr->yPos() == PositionBottom)
curr->setYPos(y + maxHeight - curr->height());
else {
if (!curr->hasTextChildren() && !strictMode)
childAffectsTopBottomPos = false;
curr->setYPos(curr->yPos() + y + maxAscent - curr->baseline());
}
int newY = curr->yPos();
int newHeight = curr->height();
int newBaseline = curr->baseline();
if (curr->isText() || curr->isInlineFlowBox()) {
const QFontMetrics &fm = curr->object()->fontMetrics( m_firstLine );
newBaseline = fm.ascent();
newY += curr->baseline() - newBaseline;
newHeight = newBaseline+fm.descent();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -