📄 render_line.cpp
字号:
bg, my, mh, _tx, _ty, w, h, borderLeft(), borderRight()); else { // We have a background image that spans multiple lines. // We need to adjust _tx and _ty by the width of all previous lines. // Think of background painting on inlines as though you had one long line, a single continuous // strip. Even though that strip has been broken up across multiple lines, you still paint it // as though you had one single line. This means each line has to pick up the background where // the previous line left off. int startX = _tx - xOffsetOnLine; int totalWidth = xOffsetOnLine; for (InlineRunBox* curr = this; curr; curr = curr->nextLineBox()) totalWidth += curr->width(); QRect clipRect(_tx, _ty, width(), height()); clipRect = p->xForm(clipRect); p->save(); p->addClip(clipRect); object()->paintBackgroundExtended(p, object()->style()->backgroundColor(), object()->style()->backgroundImage(), my, mh, startX, _ty, totalWidth, h, borderLeft(), borderRight()); p->restore(); } // :first-line cannot be used to put borders on a line. Always paint borders with our // non-first-line style. if (parent() && object()->style()->hasBorder()) object()->paintBorder(p, _tx, _ty, w, h, object()->style(), includeLeftEdge(), includeRightEdge()); }}static bool shouldDrawDecoration(RenderObject* obj){ bool shouldDraw = false; for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling()) { if (curr->isInlineFlow()) { shouldDraw = true; break; } else if (curr->isText() && !curr->isBR() && (curr->style()->whiteSpace() == PRE || !curr->element() || !curr->element()->containsOnlyWhitespace())) { shouldDraw = true; break; } } return shouldDraw;}void InlineFlowBox::paintDecorations(RenderObject::PaintInfo& i, int _tx, int _ty, bool paintedChildren){ // Now paint our text decorations. We only do this if we aren't in quirks mode (i.e., in // almost-strict mode or strict mode). QPainter* p = i.p; _tx += m_x; _ty += m_y; RenderStyle* styleToUse = object()->style(m_firstLine); int deco = parent() ? styleToUse->textDecoration() : styleToUse->textDecorationsInEffect(); if (deco != TDNONE && ((!paintedChildren && ((deco & UNDERLINE) || (deco & OVERLINE))) || (paintedChildren && (deco & LINE_THROUGH))) && shouldDrawDecoration(object())) { int x = m_x + borderLeft() + paddingLeft(); int w = m_width - (borderLeft() + paddingLeft() + borderRight() + paddingRight()); RootInlineBox* rootLine = root(); if (rootLine->ellipsisBox()) { int ellipsisX = rootLine->ellipsisBox()->xPos(); int ellipsisWidth = rootLine->ellipsisBox()->width(); // FIXME: Will need to work with RTL if (rootLine == this) { if (x + w >= ellipsisX + ellipsisWidth) w -= (x + w - ellipsisX - ellipsisWidth); } else { if (x >= ellipsisX) return; if (x + w >= ellipsisX) w -= (x + w - ellipsisX); } } #if APPLE_CHANGES // Set up the appropriate text-shadow effect for the decoration. // FIXME: Support multiple shadow effects. Need more from the CG API before we can do this. bool setShadow = false; if (styleToUse->textShadow()) { p->setShadow(styleToUse->textShadow()->x, styleToUse->textShadow()->y, styleToUse->textShadow()->blur, styleToUse->textShadow()->color); setShadow = true; }#endif // We must have child boxes and have decorations defined. _tx += borderLeft() + paddingLeft(); QColor underline, overline, linethrough; underline = overline = linethrough = styleToUse->color(); if (!parent()) object()->getTextDecorationColors(deco, underline, overline, linethrough); if (styleToUse->font() != p->font()) p->setFont(styleToUse->font()); if (deco & UNDERLINE && !paintedChildren) { p->setPen(underline); p->drawLineForText(_tx, _ty, m_baseline, w); } if (deco & OVERLINE && !paintedChildren) { p->setPen(overline); p->drawLineForText(_tx, _ty, 0, w); } if (deco & LINE_THROUGH && paintedChildren) { p->setPen(linethrough); p->drawLineForText(_tx, _ty, 2*m_baseline/3, w); }#if APPLE_CHANGES if (setShadow) p->clearShadow();#endif }}InlineBox* InlineFlowBox::firstLeafChild(){ InlineBox *box = firstChild(); while (box) { InlineBox* next = 0; if (!box->isInlineFlowBox()) break; next = static_cast<InlineFlowBox*>(box)->firstChild(); if (!next) break; box = next; } return box;}InlineBox* InlineFlowBox::lastLeafChild(){ InlineBox *box = lastChild(); while (box) { InlineBox* next = 0; if (!box->isInlineFlowBox()) break; next = static_cast<InlineFlowBox*>(box)->lastChild(); if (!next) break; box = next; } return box;}InlineBox* InlineFlowBox::closestChildForXPos(int _x, int _tx){ if (_x < _tx + firstChild()->m_x) // if the x coordinate is to the left of the first child return firstChild(); else if (_x >= _tx + lastChild()->m_x + lastChild()->m_width) // if the x coordinate is to the right of the last child return lastChild(); else // look for the closest child; // check only the right edges, since the left edge of the first // box has already been checked for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) if (_x < _tx + box->m_x + box->m_width) return box; return 0;}bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth){ for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) { if (!box->canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth)) return false; } return true;}int InlineFlowBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox){ int result = -1; for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) { int currResult = box->placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox); if (currResult != -1 && result == -1) result = currResult; } return result;}void InlineFlowBox::clearTruncation(){ for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) box->clearTruncation();}void EllipsisBox::paint(RenderObject::PaintInfo& i, int _tx, int _ty){ QPainter* p = i.p; RenderStyle* _style = m_firstLine ? m_object->style(true) : m_object->style(); if (_style->font() != p->font()) p->setFont(_style->font()); const Font* font = &_style->htmlFont(); QColor textColor = _style->color(); if (textColor != p->pen().color()) p->setPen(textColor); bool setShadow = false; if (_style->textShadow()) { p->setShadow(_style->textShadow()->x, _style->textShadow()->y, _style->textShadow()->blur, _style->textShadow()->color); setShadow = true; } const DOMString& str = m_str.string(); font->drawText(p, m_x + _tx, m_y + _ty + m_baseline, (str.implementation())->s, str.length(), 0, str.length(), 0, QPainter::LTR, _style->visuallyOrdered()); if (setShadow) p->clearShadow(); if (m_markupBox) { // Paint the markup box _tx += m_x + m_width - m_markupBox->xPos(); _ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline()); m_markupBox->object()->paint(i, _tx, _ty); }}bool EllipsisBox::nodeAtPoint(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inBox){ if (m_markupBox) { _tx += m_x + m_width - m_markupBox->xPos(); _ty += m_y + m_baseline - (m_markupBox->yPos() + m_markupBox->baseline()); inBox |= m_markupBox->object()->nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox); } return inBox;}void RootInlineBox::detach(RenderArena* arena){ detachEllipsisBox(arena); InlineFlowBox::detach(arena);}void RootInlineBox::detachEllipsisBox(RenderArena* arena){ if (m_ellipsisBox) { m_ellipsisBox->detach(arena); m_ellipsisBox = 0; }}void RootInlineBox::clearTruncation(){ if (m_ellipsisBox) { detachEllipsisBox(m_object->renderArena()); InlineFlowBox::clearTruncation(); }}bool RootInlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth){ // First sanity-check the unoverflowed width of the whole line to see if there is sufficient room. int delta = ltr ? lineBoxEdge - blockEdge : blockEdge - lineBoxEdge; if (width() - delta < ellipsisWidth) return false; // Next iterate over all the line boxes on the line. If we find a replaced element that intersects // then we refuse to accommodate the ellipsis. Otherwise we're ok. return InlineFlowBox::canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth);}void RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr, bool ltr, int blockEdge, int ellipsisWidth, InlineBox* markupBox){ // Create an ellipsis box. m_ellipsisBox = new (m_object->renderArena()) EllipsisBox(m_object, ellipsisStr, this, ellipsisWidth - (markupBox ? markupBox->width() : 0), yPos(), height(), baseline(), !prevRootBox(), markupBox); if (ltr && (xPos() + width() + ellipsisWidth) <= blockEdge) { m_ellipsisBox->m_x = xPos() + width(); return; } // Now attempt to find the nearest glyph horizontally and place just to the right (or left in RTL) // of that glyph. Mark all of the objects that intersect the ellipsis box as not painting (as being // truncated). bool foundBox = false; m_ellipsisBox->m_x = placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox);}int RootInlineBox::placeEllipsisBox(bool ltr, int blockEdge, int ellipsisWidth, bool& foundBox){ int result = InlineFlowBox::placeEllipsisBox(ltr, blockEdge, ellipsisWidth, foundBox); if (result == -1) result = ltr ? blockEdge - ellipsisWidth : blockEdge; return result;}void RootInlineBox::paintEllipsisBox(RenderObject::PaintInfo& i, int _tx, int _ty) const{ if (m_ellipsisBox) m_ellipsisBox->paint(i, _tx, _ty);}bool RootInlineBox::hitTestEllipsisBox(RenderObject::NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inBox){ if (m_ellipsisBox) inBox |= m_ellipsisBox->nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inBox); return inBox;}void RootInlineBox::adjustPosition(int dx, int dy){ InlineFlowBox::adjustPosition(dx, dy); m_topOverflow += dy; m_bottomOverflow += dy; m_blockHeight += dy;}void RootInlineBox::childRemoved(InlineBox* box){ if (box->object() == m_lineBreakObj) setLineBreakInfo(0,0); RootInlineBox* prev = prevRootBox(); if (prev && prev->lineBreakObj() == box->object()) { prev->setLineBreakInfo(0,0); prev->markDirty(); }}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -