📄 render_object.cpp
字号:
if ( state.m_lastNode ) { node = state.m_lastNode; offset = state.m_lastOffset; //kdDebug(6030) << "RenderObject::checkSelectionPoint " << this << " before this child " // << node << "-> returning SelectionPointInside, offset=" << offset << endl; return SelectionPointInside; } else { node = nod; offset = off; //kdDebug(6030) << "RenderObject::checkSelectionPoint " << this << " before us -> returning SelectionPointBefore " << node << "/" << offset << endl; return SelectionPointBefore; } break; case SelectionPointAfter: if (state.m_afterInLine) break; // fall through case SelectionPointAfterInLine: if (pos == SelectionPointAfterInLine) state.m_afterInLine = true; //kdDebug(6030) << "RenderObject::checkSelectionPoint: selection after: " << nod << " offset: " << off << " afterInLine: " << state.m_afterInLine << endl; state.m_lastNode = nod; state.m_lastOffset = off; // No "return" here, obviously. We must keep looking into the children. break; } } // If we are after the last child, return lastNode/lastOffset // But lastNode can be 0L if there is no child, for instance. if ( state.m_lastNode ) { node = state.m_lastNode; offset = state.m_lastOffset; } //kdDebug(6030) << "fallback - SelectionPointAfter node=" << node << " offset=" << offset << endl; return SelectionPointAfter;}bool RenderObject::mouseInside() const{ if (!m_mouseInside && continuation()) return continuation()->mouseInside(); return m_mouseInside;}bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside){ int tx = _tx + xPos(); int ty = _ty + yPos(); inside |= ( style()->visibility() != HIDDEN && (_y >= ty) && (_y < ty + height()) && (_x >= tx) && (_x < tx + width())) || isRoot() || isBody(); bool inOverflowRect = inside; if ( !inOverflowRect ) { QRect overflowRect( tx, ty, overflowWidth(), overflowHeight() ); inOverflowRect = overflowRect.contains( _x, _y ); } // ### table should have its own, more performant method if (hitTestAction != HitTestSelfOnly && (( !isRenderBlock() || !static_cast<RenderBlock*>( this )->isPointInScrollbar( _x, _y, _tx, _ty )) && (overhangingContents() || inOverflowRect || isInline() || isRoot() || isCanvas() || isTableRow() || isTableSection() || inside || mouseInside() ))) { if ( hitTestAction == HitTestChildrenOnly ) inside = false; if ( style()->hidesOverflow() && layer() ) layer()->subtractScrollOffset(tx, ty); for (RenderObject* child = lastChild(); child; child = child->previousSibling()) if (!child->layer() && child->nodeAtPoint(info, _x, _y, tx, ty, HitTestAll)) inside = true; } if (inside) { if (!info.innerNode() && !isInline() && continuation()) { // We are in the margins of block elements that are part of a continuation. In // this case we're actually still inside the enclosing inline element that was // split. Go ahead and set our inner node accordingly. info.setInnerNode(continuation()->element()); if (!info.innerNonSharedNode()) info.setInnerNonSharedNode(continuation()->element()); } if (info.innerNode() && info.innerNode()->renderer() && !info.innerNode()->renderer()->isInline() && element() && isInline()) { // Within the same layer, inlines are ALWAYS fully above blocks. Change inner node. info.setInnerNode(element()); // Clear everything else. info.setInnerNonSharedNode(0); info.setURLElement(0); } if (!info.innerNode() && element()) info.setInnerNode(element()); if(!info.innerNonSharedNode() && element()) info.setInnerNonSharedNode(element()); } return inside;}short RenderObject::verticalPositionHint( bool firstLine ) const{ short vpos = m_verticalPosition; if ( m_verticalPosition == PositionUndefined || firstLine ) { vpos = getVerticalPosition( firstLine ); if ( !firstLine ) const_cast<RenderObject *>(this)->m_verticalPosition = vpos; } return vpos;}short RenderObject::getVerticalPosition( bool firstLine, RenderObject* ref ) const{ // vertical align for table cells has a different meaning int vpos = 0; if ( !isTableCell() && isInline() ) { EVerticalAlign va = style()->verticalAlign(); if ( va == TOP ) { vpos = PositionTop; } else if ( va == BOTTOM ) { vpos = PositionBottom; } else { if (!ref) ref = parent(); bool checkParent = ref->isInline() && !ref->isReplacedBlock() && !( ref->style()->verticalAlign() == TOP || ref->style()->verticalAlign() == BOTTOM ); vpos = checkParent ? ref->verticalPositionHint( firstLine ) : 0; // don't allow elements nested inside text-top to have a different valignment. if ( va == BASELINE ) return vpos; else if ( va == LENGTH ) return vpos - style()->verticalAlignLength().width( lineHeight( firstLine ) ); const QFont &f = ref->font( firstLine ); int fontheight = ref->lineHeight( firstLine ); int fontsize = f.pixelSize(); int halfleading = ( fontheight - fontsize ) / 2; if ( va == SUB ) vpos += fontsize/5 + 1; else if ( va == SUPER ) vpos -= fontsize/3 + 1; else if ( va == TEXT_TOP ) {// qDebug( "got TEXT_TOP vertical pos hint" );// qDebug( "parent:" );// qDebug( "CSSLH: %d, CSS_FS: %d, basepos: %d", fontheight, fontsize, ref->baselinePosition( firstLine ) );// qDebug( "this:" );// qDebug( "CSSLH: %d, CSS_FS: %d, basepos: %d", lineHeight( firstLine ), style()->font().pixelSize(), baselinePosition( firstLine ) ); vpos += ( baselinePosition( firstLine ) - ref->baselinePosition( firstLine ) + halfleading ); } else if ( va == MIDDLE ) { QRect b = QFontMetrics(f).boundingRect('x'); vpos += -b.height()/2 - lineHeight( firstLine )/2 + baselinePosition( firstLine ); } else if ( va == TEXT_BOTTOM ) { vpos += QFontMetrics(f).descent(); if ( !isReplaced() ) vpos -= fontMetrics(firstLine).descent(); } else if ( va == BASELINE_MIDDLE ) vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine ); } } return vpos;}short RenderObject::lineHeight( bool firstLine ) const{ // Inline blocks are replaced elements. Otherwise, just pass off to // the base class. If we're being queried as though we're the root line // box, then the fact that we're an inline-block is irrelevant, and we behave // just like a block. if (isReplaced() && (!isInlineBlockOrInlineTable() || !needsLayout())) return height()+marginTop()+marginBottom(); Length lh; if( firstLine && hasFirstLine() ) { RenderStyle *pseudoStyle = style()->getPseudoStyle(RenderStyle::FIRST_LINE); if ( pseudoStyle ) lh = pseudoStyle->lineHeight(); } else lh = style()->lineHeight(); // its "unset", choose nice default if ( lh.value() < 0 ) return style()->fontMetrics().lineSpacing(); if ( lh.isPercent() ) return lh.minWidth( style()->font().pixelSize() ); // its fixed return lh.value();}short RenderObject::baselinePosition( bool firstLine ) const{ // Inline blocks are replaced elements. Otherwise, just pass off to // the base class. If we're being queried as though we're the root line // box, then the fact that we're an inline-block is irrelevant, and we behave // just like a block. if (isReplaced() && (!isInlineBlockOrInlineTable() || !needsLayout())) return height()+marginTop()+marginBottom(); const QFontMetrics &fm = fontMetrics( firstLine ); return fm.ascent() + ( lineHeight( firstLine) - fm.height() ) / 2;}void RenderObject::invalidateVerticalPositions(){ m_verticalPosition = PositionUndefined; RenderObject *child = firstChild(); while( child ) { child->invalidateVerticalPositions(); child = child->nextSibling(); }}void RenderObject::recalcMinMaxWidths(){ KHTMLAssert( m_recalcMinMax );#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;#endif RenderObject *child = firstChild(); int cmin=0; int cmax=0; while( child ) { bool test = false; if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) { cmin = child->minWidth(); cmax = child->maxWidth(); test = true; } if ( child->m_recalcMinMax ) child->recalcMinMaxWidths(); if ( !child->m_minMaxKnown ) child->calcMinMaxWidth(); if ( m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()) ) m_minMaxKnown = false; child = child->nextSibling(); } // we need to recalculate, if the contains inline children, as the change could have // happened somewhere deep inside the child tree if ( ( !isInline() || isReplacedBlock() ) && childrenInline() ) m_minMaxKnown = false; if ( !m_minMaxKnown ) calcMinMaxWidth(); m_recalcMinMax = false;}void RenderObject::scheduleRelayout(RenderObject *clippedObj){ if (!isCanvas()) return; KHTMLView *view = static_cast<RenderCanvas *>(this)->view(); if ( view ) view->scheduleRelayout(clippedObj);}void RenderObject::removeLeftoverAnonymousBoxes(){}InlineBox* RenderObject::createInlineBox(bool /*makePlaceHolderBox*/, bool /*isRootLineBox*/){ KHTMLAssert(false); return 0;}void RenderObject::getTextDecorationColors(int decorations, QColor& underline, QColor& overline, QColor& linethrough, bool quirksMode){ RenderObject* curr = this; do { RenderStyle *st = curr->style(); int currDecs = st->textDecoration(); if (currDecs) { if (currDecs & UNDERLINE) { decorations &= ~UNDERLINE; underline = st->color(); } if (currDecs & OVERLINE) { decorations &= ~OVERLINE; overline = st->color(); } if (currDecs & LINE_THROUGH) { decorations &= ~LINE_THROUGH; linethrough = st->color(); } } curr = curr->parent(); if (curr && curr->isRenderBlock() && curr->continuation()) curr = curr->continuation(); } while (curr && decorations && (!quirksMode || !curr->element() || (curr->element()->id() != ID_A && curr->element()->id() != ID_FONT))); // If we bailed out, use the element we bailed out at (typically a <font> or <a> element). if (decorations && curr) { RenderStyle *st = curr->style(); if (decorations & UNDERLINE) underline = st->color(); if (decorations & OVERLINE) overline = st->color(); if (decorations & LINE_THROUGH) linethrough = st->color(); }}int RenderObject::maximalOutlineSize(PaintAction p) const{ if (p != PaintActionOutline) return 0; return static_cast<RenderCanvas*>(document()->renderer())->maximalOutlineSize();}void RenderObject::collectBorders(QValueList<CollapsedBorderValue>& borderStyles){ for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) curr->collectBorders(borderStyles);}bool RenderObject::flowAroundFloats() const{ return isReplaced() || hasOverflowClip() || style()->flowAroundFloats();}bool RenderObject::usesLineWidth() const{ // 1. All auto-width objects that avoid floats should always use lineWidth // 2. For objects with a specified width, we match WinIE's behavior: // (a) tables use contentWidth // (b) <hr>s use lineWidth // (c) all other objects use lineWidth in quirks mode and contentWidth in strict mode. return (flowAroundFloats() && (style()->width().isVariable() || isHR() || (style()->htmlHacks() && !isTable())));}bool RenderObject::hasCounter(const QString& counter) const{ if (style() && (!isText() || isCounter())) { if (lookupCounter(counter)) return true; if (style()->hasCounterReset(counter)) { return true; } else if (style()->hasCounterIncrement(counter)) { return true; } } if (counter == "list-item") { if (isListItem()) return true; if (element() && ( element()->id() == ID_OL || element()->id() == ID_UL || element()->id() == ID_MENU || element()->id() == ID_DIR)) return true; } else if (counter == "-khtml-quotes" && isQuote()) { return (static_cast<const RenderQuote*>(this)->quoteCount() != 0); } return false;}CounterNode* RenderObject::getCounter(const QString& counter, bool view, bool counters){// kdDebug( 6040 ) << renderName() << " getCounter(" << counter << ")" << endl; if (!style()) return 0; if (isText() && !isCounter()) return 0; CounterNode *i = lookupCounter(counter); if (i) return i; int val = 0; if (style()->hasCounterReset(counter) || isRoot()) { i = new CounterReset(this); val = style()->counterReset(counter);// kdDebug( 6040 ) << renderName() << " counter-reset: " << counter << " " << val << endl; } else if (style()->hasCounterIncrement(counter)) { i = new CounterNode(this); val = style()->counterIncrement(counter);// kdDebug( 6040 ) << renderName() << " counter-increment: " << counter << " " << val << endl; } else if (counter == "list-item") { if (isListItem()) { if (element() && element()->id() ==
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -