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. RenderObject* curr = object(); while (curr && !curr->element()) curr = curr->container(); bool strictMode = (curr && curr->element()->getDocument()->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); setOverflowPositions(topPosition, bottomPosition); // Shrink boxes with no text children in quirks and almost strict mode. if (!strictMode) shrinkBoxesWithNoTextChildren(topPosition, bottomPosition); heightOfBlock += maxHeight; }
static RenderObject* getParentOfFirstLineBox(RenderObject* curr, RenderObject* marker) { RenderObject* firstChild = curr->firstChild(); if (!firstChild) return 0; for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) { if (currChild == marker) continue; if (currChild->isInline()) return curr; if (currChild->isFloating() || currChild->isPositioned()) continue; if (currChild->isTable() || !currChild->isRenderBlock()) break; if (currChild->style()->htmlHacks() && currChild->element() && (currChild->element()->hasTagName(ulTag)|| currChild->element()->hasTagName(olTag))) break; RenderObject* lineBox = getParentOfFirstLineBox(currChild, marker); if (lineBox) return lineBox; } return 0; }
RenderObject* RenderFieldset::findLegend() const { for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) { if (!legend->isFloatingOrPositioned() && legend->element() && legend->element()->hasTagName(legendTag)) return legend; } return 0; }
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()->preserveWS() || !curr->element() || !curr->element()->containsOnlyWhitespace())) { shouldDraw = true; break; } } return shouldDraw; }
bool Position::hasRenderedNonAnonymousDescendantsWithHeight(RenderObject* renderer) { RenderObject* stop = renderer->nextInPreOrderAfterChildren(); for (RenderObject *o = renderer->firstChild(); o && o != stop; o = o->nextInPreOrder()) if (o->element() && o->height()) return true; return false; }
// This needs to be static so it can be called by canIncreaseSelectionListLevel and canDecreaseSelectionListLevel static bool getStartEndListChildren(const Selection& selection, Node*& start, Node*& end) { if (selection.isNone()) return false; // start must be in a list child Node* startListChild = enclosingListChild(selection.start().node()); if (!startListChild) return false; // end must be in a list child Node* endListChild = selection.isRange() ? enclosingListChild(selection.end().node()) : startListChild; if (!endListChild) return false; // For a range selection we want the following behavior: // - the start and end must be within the same overall list // - the start must be at or above the level of the rest of the range // - if the end is anywhere in a sublist lower than start, the whole sublist gets moved // In terms of this function, this means: // - endListChild must start out being be a sibling of startListChild, or be in a // sublist of startListChild or a sibling // - if endListChild is in a sublist of startListChild or a sibling, it must be adjusted // to be the ancestor that is startListChild or its sibling while (startListChild->parentNode() != endListChild->parentNode()) { endListChild = endListChild->parentNode(); if (!endListChild) return false; } // if the selection ends on a list item with a sublist, include the entire sublist if (endListChild->renderer()->isListItem()) { RenderObject* r = endListChild->renderer()->nextSibling(); if (r && isListElement(r->element())) endListChild = r->element(); } start = startListChild; end = endListChild; return true; }
static VisiblePosition endPositionForLine(const VisiblePosition& c) { if (c.isNull()) return VisiblePosition(); RootInlineBox *rootBox = rootBoxForLine(c); if (!rootBox) { // There are VisiblePositions at offset 0 in blocks without // RootInlineBoxes, like empty editable blocks and bordered blocks. Position p = c.deepEquivalent(); if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.offset() == 0) return c; return VisiblePosition(); } // Generated content (e.g. list markers and CSS :before and :after // pseudoelements) have no corresponding DOM element, and so cannot be // represented by a VisiblePosition. Use whatever precedes instead. Node *endNode; InlineBox *endBox = rootBox->lastLeafChild(); while (1) { if (!endBox) return VisiblePosition(); RenderObject *endRenderer = endBox->object(); if (!endRenderer) return VisiblePosition(); endNode = endRenderer->element(); if (endNode) break; endBox = endBox->prevLeafChild(); } int endOffset = 1; if (endNode->hasTagName(brTag)) { endOffset = 0; } else if (endBox->isInlineTextBox()) { InlineTextBox *endTextBox = static_cast<InlineTextBox *>(endBox); endOffset = endTextBox->m_start; if (!endTextBox->isLineBreak()) endOffset += endTextBox->m_len; } return VisiblePosition(endNode, endOffset, VP_UPSTREAM_IF_POSSIBLE); }
static VisiblePosition startPositionForLine(const VisiblePosition& c) { if (c.isNull()) return VisiblePosition(); RootInlineBox *rootBox = rootBoxForLine(c); if (!rootBox) { // There are VisiblePositions at offset 0 in blocks without // RootInlineBoxes, like empty editable blocks and bordered blocks. Position p = c.deepEquivalent(); if (p.node()->renderer() && p.node()->renderer()->isRenderBlock() && p.offset() == 0) return positionAvoidingFirstPositionInTable(c); return VisiblePosition(); } // Generated content (e.g. list markers and CSS :before and :after // pseudoelements) have no corresponding DOM element, and so cannot be // represented by a VisiblePosition. Use whatever follows instead. InlineBox *startBox = rootBox->firstLeafChild(); Node *startNode; while (1) { if (!startBox) return VisiblePosition(); RenderObject *startRenderer = startBox->object(); if (!startRenderer) return VisiblePosition(); startNode = startRenderer->element(); if (startNode) break; startBox = startBox->nextLeafChild(); } int startOffset = 0; if (startBox->isInlineTextBox()) { InlineTextBox *startTextBox = static_cast<InlineTextBox *>(startBox); startOffset = startTextBox->m_start; } VisiblePosition visPos = VisiblePosition(startNode, startOffset, DOWNSTREAM); return positionAvoidingFirstPositionInTable(visPos); }
AccessibilityObject* AccessibilityTableRow::headerObject() { AccessibilityChildrenVector rowChildren = children(); if (!rowChildren.size()) return 0; // check the first element in the row to see if it is a TH element AccessibilityObject* cell = rowChildren[0].get(); if (!cell->isTableCell()) return 0; RenderObject* cellRenderer = static_cast<AccessibilityTableCell*>(cell)->renderer(); if (!cellRenderer) return 0; Node* cellNode = cellRenderer->element(); if (!cellNode || !cellNode->hasTagName(thTag)) return 0; return cell; }
void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>* timer) { // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate // updateRendering. It will then call back to us with new information. bool animating = false; RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); it != animationsEnd; ++it) { RenderObject* renderer = it->first; CompositeAnimation* compAnim = it->second; if (!compAnim->suspended() && compAnim->animating()) { animating = true; compAnim->setAnimating(false); Node* node = renderer->element(); ASSERT(!node || (node->document() && !node->document()->inPageCache())); node->setChanged(AnimationStyleChange); } } m_frame->document()->updateRendering(); updateAnimationTimer(); }
VisiblePosition nextLinePosition(const VisiblePosition &visiblePosition, int x) { Position p = visiblePosition.deepEquivalent(); Node *node = p.node(); Node* highestRoot = highestEditableRoot(p); if (!node) return VisiblePosition(); node->document()->updateLayoutIgnorePendingStylesheets(); RenderObject *renderer = node->renderer(); if (!renderer) return VisiblePosition(); RenderBlock *containingBlock = 0; RootInlineBox *root = 0; InlineBox* box; int ignoredCaretOffset; visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset); if (box) { root = box->root()->nextRootBox(); if (root) containingBlock = renderer->containingBlock(); } if (!root) { // This containing editable block does not have a next line. // Need to move forward to next containing editable block in this root editable // block and find the first root line box in that block. Node* startBlock = enclosingBlock(node); Node* n = nextLeafWithSameEditability(node, p.offset()); while (n && startBlock == enclosingBlock(n)) n = nextLeafWithSameEditability(n); while (n) { if (highestEditableRoot(Position(n, 0)) != highestRoot) break; Position pos(n, caretMinOffset(n)); if (pos.isCandidate()) { ASSERT(n->renderer()); pos.getInlineBoxAndOffset(DOWNSTREAM, box, ignoredCaretOffset); if (box) { // next root line box found root = box->root(); containingBlock = n->renderer()->containingBlock(); break; } return VisiblePosition(pos, DOWNSTREAM); } n = nextLeafWithSameEditability(n); } } if (root) { // FIXME: Can be wrong for multi-column layout. int absx, absy; containingBlock->absolutePositionForContent(absx, absy); if (containingBlock->hasOverflowClip()) containingBlock->layer()->subtractScrollOffset(absx, absy); RenderObject *renderer = root->closestLeafChildForXPos(x - absx, isEditablePosition(p))->object(); Node* node = renderer->element(); if (editingIgnoresContent(node)) return Position(node->parent(), node->nodeIndex()); return renderer->positionForCoordinates(x - absx, root->topOverflow()); } // Could not find a next line. This means we must already be on the last line. // Move to the end of the content in this block, which effectively moves us // to the end of the line we're on. Element* rootElement = node->isContentEditable() ? node->rootEditableElement() : node->document()->documentElement(); return VisiblePosition(rootElement, rootElement ? rootElement->childNodeCount() : 0, DOWNSTREAM); }