本文整理汇总了C++中RenderObject类的典型用法代码示例。如果您正苦于以下问题:C++ RenderObject类的具体用法?C++ RenderObject怎么用?C++ RenderObject使用的例子?那么, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了RenderObject类的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: isTableStructureNode
bool isTableStructureNode(const Node *node)
{
RenderObject *r = node->renderer();
return (r && (r->isTableCell() || r->isTableRow() || r->isTableSection() || r->isTableCol()));
}
示例2: layoutSizeOfNearestViewportChanged
void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
{
bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start);
bool transformChanged = transformToRootChanged(start);
HashSet<RenderObject*> notlayoutedObjects;
for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
bool needsLayout = selfNeedsLayout;
bool childEverHadLayout = child->everHadLayout();
if (transformChanged) {
// If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true).
if (child->isSVGText())
toRenderSVGText(child)->setNeedsTextMetricsUpdate();
needsLayout = true;
}
if (layoutSizeChanged) {
// When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) {
if (element->hasRelativeLengths()) {
// When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
if (child->isSVGShape())
toRenderSVGShape(child)->setNeedsShapeUpdate();
else if (child->isSVGText()) {
toRenderSVGText(child)->setNeedsTextMetricsUpdate();
toRenderSVGText(child)->setNeedsPositioningValuesUpdate();
}
needsLayout = true;
}
}
}
SubtreeLayoutScope layoutScope(*child);
// Resource containers are nasty: they can invalidate clients outside the current SubtreeLayoutScope.
// Since they only care about viewport size changes (to resolve their relative lengths), we trigger
// their invalidation directly from SVGSVGElement::svgAttributeChange() or at a higher
// SubtreeLayoutScope (in RenderView::layout()).
if (needsLayout && !child->isSVGResourceContainer())
layoutScope.setNeedsLayout(child);
layoutResourcesIfNeeded(child);
if (child->needsLayout()) {
child->layout();
// Renderers are responsible for repainting themselves when changing, except
// for the initial paint to avoid potential double-painting caused by non-sensical "old" bounds.
// We could handle this in the individual objects, but for now it's easier to have
// parent containers call repaint(). (RenderBlock::layout* has similar logic.)
if (!childEverHadLayout && !RuntimeEnabledFeatures::repaintAfterLayoutEnabled())
child->repaint();
} else if (layoutSizeChanged)
notlayoutedObjects.add(child);
}
if (!layoutSizeChanged) {
ASSERT(notlayoutedObjects.isEmpty());
return;
}
// If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path.
HashSet<RenderObject*>::iterator end = notlayoutedObjects.end();
for (HashSet<RenderObject*>::iterator it = notlayoutedObjects.begin(); it != end; ++it)
invalidateResourcesOfChildren(*it);
}
示例3: writeSVGResourceContainer
void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent)
{
writeStandardPrefix(ts, object, indent);
Element* element = toElement(object.node());
const AtomicString& id = element->getIdAttribute();
writeNameAndQuotedValue(ts, "id", id);
RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer();
ASSERT(resource);
if (resource->resourceType() == MaskerResourceType) {
RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource);
writeNameValuePair(ts, "maskUnits", masker->maskUnits());
writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits());
ts << "\n";
#if ENABLE(FILTERS)
} else if (resource->resourceType() == FilterResourceType) {
RenderSVGResourceFilter* filter = static_cast<RenderSVGResourceFilter*>(resource);
writeNameValuePair(ts, "filterUnits", filter->filterUnits());
writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits());
ts << "\n";
// Creating a placeholder filter which is passed to the builder.
FloatRect dummyRect;
RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyRect, dummyRect, dummyRect, true);
if (auto builder = filter->buildPrimitives(dummyFilter.get())) {
if (FilterEffect* lastEffect = builder->lastEffect())
lastEffect->externalRepresentation(ts, indent + 1);
}
#endif
} else if (resource->resourceType() == ClipperResourceType) {
RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource);
writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits());
ts << "\n";
} else if (resource->resourceType() == MarkerResourceType) {
RenderSVGResourceMarker* marker = static_cast<RenderSVGResourceMarker*>(resource);
writeNameValuePair(ts, "markerUnits", marker->markerUnits());
ts << " [ref at " << marker->referencePoint() << "]";
ts << " [angle=";
if (marker->angle() == -1)
ts << "auto" << "]\n";
else
ts << marker->angle() << "]\n";
} else if (resource->resourceType() == PatternResourceType) {
RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource);
// Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may
// link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties()
PatternAttributes attributes;
pattern->patternElement().collectPatternAttributes(attributes);
writeNameValuePair(ts, "patternUnits", attributes.patternUnits());
writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits());
AffineTransform transform = attributes.patternTransform();
if (!transform.isIdentity())
ts << " [patternTransform=" << transform << "]";
ts << "\n";
} else if (resource->resourceType() == LinearGradientResourceType) {
RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource);
// Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may
// link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties()
LinearGradientAttributes attributes;
gradient->linearGradientElement().collectGradientAttributes(attributes);
writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());
ts << " [start=" << gradient->startPoint(attributes) << "] [end=" << gradient->endPoint(attributes) << "]\n";
} else if (resource->resourceType() == RadialGradientResourceType) {
RenderSVGResourceRadialGradient* gradient = static_cast<RenderSVGResourceRadialGradient*>(resource);
// Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may
// link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties()
RadialGradientAttributes attributes;
gradient->radialGradientElement().collectGradientAttributes(attributes);
writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());
FloatPoint focalPoint = gradient->focalPoint(attributes);
FloatPoint centerPoint = gradient->centerPoint(attributes);
float radius = gradient->radius(attributes);
float focalRadius = gradient->focalRadius(attributes);
ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "] [focalRadius=" << focalRadius << "]\n";
} else
ts << "\n";
writeChildren(ts, object, indent);
}
示例4: firstChild
void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
{
// Insert :before and :after content before/after the RenderRubyRun(s)
if (child->isBeforeContent()) {
if (child->isInline()) {
// Add generated inline content normally
RenderBlockFlow::addChild(child, firstChild());
} else {
// Wrap non-inline content with an anonymous inline-block.
RenderBlock* beforeBlock = rubyBeforeBlock(this);
if (!beforeBlock) {
beforeBlock = createAnonymousRubyInlineBlock(this);
RenderBlockFlow::addChild(beforeBlock, firstChild());
}
beforeBlock->addChild(child);
}
return;
}
if (child->isAfterContent()) {
if (child->isInline()) {
// Add generated inline content normally
RenderBlockFlow::addChild(child);
} else {
// Wrap non-inline content with an anonymous inline-block.
RenderBlock* afterBlock = rubyAfterBlock(this);
if (!afterBlock) {
afterBlock = createAnonymousRubyInlineBlock(this);
RenderBlockFlow::addChild(afterBlock);
}
afterBlock->addChild(child);
}
return;
}
// If the child is a ruby run, just add it normally.
if (child->isRubyRun()) {
RenderBlockFlow::addChild(child, beforeChild);
return;
}
if (beforeChild && !isAfterContent(beforeChild)) {
// insert child into run
ASSERT(!beforeChild->isRubyRun());
RenderObject* run = beforeChild;
while (run && !run->isRubyRun())
run = run->parent();
if (run) {
run->addChild(child, beforeChild);
return;
}
ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
// Emergency fallback: fall through and just append.
}
// If the new child would be appended, try to add the child to the previous run
// if possible, or create a new run otherwise.
// (The RenderRubyRun object will handle the details)
RenderRubyRun* lastRun = lastRubyRun(this);
if (!lastRun || lastRun->hasRubyText()) {
lastRun = RenderRubyRun::staticCreateRubyRun(this);
RenderBlockFlow::addChild(lastRun, beforeChild);
}
lastRun->addChild(child);
}
示例5: afterPseudoElementRenderer
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
// Make sure we don't append things after :after-generated content if we have it.
if (!beforeChild)
beforeChild = afterPseudoElementRenderer();
if (!child->isTableCell()) {
RenderObject* last = beforeChild;
if (!last)
last = lastChild();
if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
if (beforeChild == last)
beforeChild = last->firstChild();
last->addChild(child, beforeChild);
return;
}
if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
RenderObject* cell = beforeChild->previousSibling();
if (cell && cell->isTableCell() && cell->isAnonymous()) {
cell->addChild(child);
return;
}
}
// If beforeChild is inside an anonymous cell, insert into the cell.
if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
last->parent()->addChild(child, beforeChild);
return;
}
RenderTableCell* cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
RefPtr<RenderStyle> newStyle = RenderStyle::create();
newStyle->inheritFrom(style());
newStyle->setDisplay(TABLE_CELL);
cell->setStyle(newStyle.release());
addChild(cell, beforeChild);
cell->addChild(child);
return;
}
// If the next renderer is actually wrapped in an anonymous table cell, we need to go up and find that.
while (beforeChild && beforeChild->parent() != this)
beforeChild = beforeChild->parent();
RenderTableCell* cell = toRenderTableCell(child);
// Generated content can result in us having a null section so make sure to null check our parent.
if (parent())
section()->addCell(cell, this);
ASSERT(!beforeChild || beforeChild->isTableCell());
RenderBox::addChild(cell, beforeChild);
if (beforeChild || nextSibling())
section()->setNeedsCellRecalc();
}
示例6: afterPseudoElementRenderer
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
// Make sure we don't append things after :after-generated content if we have it.
if (!beforeChild)
beforeChild = afterPseudoElementRenderer();
if (!child->isTableCell()) {
RenderObject* last = beforeChild;
if (!last)
last = lastChild();
if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
if (beforeChild == last)
beforeChild = last->firstChild();
last->addChild(child, beforeChild);
return;
}
if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
RenderObject* cell = beforeChild->previousSibling();
if (cell && cell->isTableCell() && cell->isAnonymous()) {
cell->addChild(child);
return;
}
}
// If beforeChild is inside an anonymous cell, insert into the cell.
if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
last->parent()->addChild(child, beforeChild);
return;
}
RenderTableCell* cell = RenderTableCell::createAnonymousWithParentRenderer(this);
addChild(cell, beforeChild);
cell->addChild(child);
return;
}
if (beforeChild && beforeChild->parent() != this)
beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
RenderTableCell* cell = toRenderTableCell(child);
// Generated content can result in us having a null section so make sure to null check our parent.
if (parent())
section()->addCell(cell, this);
ASSERT(!beforeChild || beforeChild->isTableCell());
RenderBox::addChild(cell, beforeChild);
if (beforeChild || nextSibling())
section()->setNeedsCellRecalc();
}
示例7: sliderTickSize
void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
{
Node* node = o->node();
if (!node)
return;
HTMLInputElement* input = node->toInputElement();
if (!input)
return;
HTMLDataListElement* dataList = static_cast<HTMLDataListElement*>(input->list());
if (!dataList)
return;
double min = input->minimum();
double max = input->maximum();
ControlPart part = o->style()->appearance();
// We don't support ticks on alternate sliders like MediaVolumeSliders.
if (part != SliderHorizontalPart && part != SliderVerticalPart)
return;
bool isHorizontal = part == SliderHorizontalPart;
IntSize thumbSize;
RenderObject* thumbRenderer = input->sliderThumbElement()->renderer();
if (thumbRenderer) {
RenderStyle* thumbStyle = thumbRenderer->style();
int thumbWidth = thumbStyle->width().intValue();
int thumbHeight = thumbStyle->height().intValue();
thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight);
thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth);
}
IntSize tickSize = sliderTickSize();
float zoomFactor = o->style()->effectiveZoom();
FloatRect tickRect;
int tickRegionSideMargin = 0;
int tickRegionWidth = 0;
IntRect trackBounds;
RenderObject* trackRenderer = input->sliderTrackElement()->renderer();
// We can ignoring transforms because transform is handled by the graphics context.
if (trackRenderer)
trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms();
IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms();
// Make position relative to the transformed ancestor element.
trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x());
trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y());
if (isHorizontal) {
tickRect.setWidth(floor(tickSize.width() * zoomFactor));
tickRect.setHeight(floor(tickSize.height() * zoomFactor));
tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
tickRegionWidth = trackBounds.width() - thumbSize.width();
} else {
tickRect.setWidth(floor(tickSize.height() * zoomFactor));
tickRect.setHeight(floor(tickSize.width() * zoomFactor));
tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
tickRegionWidth = trackBounds.height() - thumbSize.width();
}
RefPtr<HTMLCollection> options = dataList->options();
GraphicsContextStateSaver stateSaver(*paintInfo.context);
paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
for (unsigned i = 0; Node* node = options->item(i); i++) {
ASSERT(node->hasTagName(optionTag));
HTMLOptionElement* optionElement = toHTMLOptionElement(node);
String value = optionElement->value();
if (!input->isValidValue(value))
continue;
double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
double tickFraction = (parsedValue - min) / (max - min);
double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction;
double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio);
if (isHorizontal)
tickRect.setX(tickPosition);
else
tickRect.setY(tickPosition);
paintInfo.context->fillRect(tickRect);
}
}
示例8: ASSERT
void SVGResourcesCycleSolver::resolveCycles()
{
ASSERT(m_allResources.isEmpty());
#if DEBUG_CYCLE_DETECTION > 0
fprintf(stderr, "\nBefore cycle detection:\n");
m_resources->dump(m_renderer);
#endif
// Stash all resources into a HashSet for the ease of traversing.
HashSet<RenderSVGResourceContainer*> localResources;
m_resources->buildSetOfResources(localResources);
ASSERT(!localResources.isEmpty());
// Add all parent resource containers to the HashSet.
HashSet<RenderSVGResourceContainer*> parentResources;
RenderObject* parent = m_renderer->parent();
while (parent) {
if (parent->isSVGResourceContainer())
parentResources.add(toRenderSVGResourceContainer(parent));
parent = parent->parent();
}
#if DEBUG_CYCLE_DETECTION > 0
fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n");
{
fprintf(stderr, "Local resources:\n");
HashSet<RenderSVGResourceContainer*>::iterator end = localResources.end();
for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it)
fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
fprintf(stderr, "Parent resources:\n");
end = parentResources.end();
for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it)
fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
}
#endif
// Build combined set of local and parent resources.
m_allResources = localResources;
HashSet<RenderSVGResourceContainer*>::iterator end = parentResources.end();
for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it)
m_allResources.add(*it);
// If we're a resource, add ourselves to the HashSet.
if (m_renderer->isSVGResourceContainer())
m_allResources.add(toRenderSVGResourceContainer(m_renderer));
ASSERT(!m_allResources.isEmpty());
// The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer'
// references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it.
end = localResources.end();
for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) {
RenderSVGResourceContainer* resource = *it;
if (parentResources.contains(resource) || resourceContainsCycles(resource))
breakCycle(resource);
}
#if DEBUG_CYCLE_DETECTION > 0
fprintf(stderr, "\nAfter cycle detection:\n");
m_resources->dump(m_renderer);
#endif
m_allResources.clear();
}
示例9: paintCapsLockIndicator
bool RenderThemeGtk::paintCapsLockIndicator(const RenderObject& renderObject, const PaintInfo& paintInfo, const IntRect& rect)
{
// The other paint methods don't need to check whether painting is disabled because RenderTheme already checks it
// before calling them, but paintCapsLockIndicator() is called by RenderTextControlSingleLine which doesn't check it.
if (paintInfo.context->paintingDisabled())
return true;
int iconSize = std::min(rect.width(), rect.height());
GRefPtr<GdkPixbuf> icon = getStockIconForWidgetType(GTK_TYPE_ENTRY, GTK_STOCK_CAPS_LOCK_WARNING, gtkTextDirection(renderObject.style().direction()), 0, getIconSizeForPixelSize(iconSize));
// Only re-scale the icon when it's smaller than the minimum icon size.
if (iconSize >= gtkIconSizeMenu)
iconSize = gdk_pixbuf_get_height(icon.get());
// GTK+ locates the icon right aligned in the entry. The given rectangle is already
// centered vertically by RenderTextControlSingleLine.
IntRect iconRect(rect.x() + rect.width() - iconSize,
rect.y() + (rect.height() - iconSize) / 2,
iconSize, iconSize);
paintGdkPixbuf(paintInfo.context, icon.get(), iconRect);
return true;
}
示例10: lastChild
RenderRubyBase* RenderRubyRun::rubyBase() const
{
RenderObject* child = lastChild();
return child && child->isRubyBase() ? static_cast<RenderRubyBase*>(child) : 0;
}
示例11: getRanges
void RenderNamedFlowThread::getRanges(Vector<RefPtr<Range> >& rangeObjects, const RenderRegion* region) const
{
LayoutUnit logicalTopForRegion;
LayoutUnit logicalBottomForRegion;
// extend the first region top to contain everything up to its logical height
if (region->isFirstRegion())
logicalTopForRegion = LayoutUnit::min();
else
logicalTopForRegion = region->logicalTopForFlowThreadContent();
// extend the last region to contain everything above its y()
if (region->isLastRegion())
logicalBottomForRegion = LayoutUnit::max();
else
logicalBottomForRegion = region->logicalBottomForFlowThreadContent();
Vector<Element*> elements;
// eliminate the contentElements that are descendants of other contentElements
for (auto it = contentElements().begin(), end = contentElements().end(); it != end; ++it) {
Element* element = *it;
if (!isContainedInElements(elements, element))
elements.append(element);
}
for (size_t i = 0; i < elements.size(); i++) {
Element* contentElement = elements.at(i);
if (!contentElement->renderer())
continue;
RefPtr<Range> range = Range::create(&contentElement->document());
bool foundStartPosition = false;
bool startsAboveRegion = true;
bool endsBelowRegion = true;
bool skipOverOutsideNodes = false;
Node* lastEndNode = 0;
for (Node* node = contentElement; node; node = nextNodeInsideContentElement(node, contentElement)) {
RenderObject* renderer = node->renderer();
if (!renderer)
continue;
LayoutRect boundingBox;
if (renderer->isRenderInline())
boundingBox = toRenderInline(renderer)->linesBoundingBox();
else if (renderer->isText())
boundingBox = toRenderText(renderer)->linesBoundingBox();
else {
boundingBox = toRenderBox(renderer)->frameRect();
if (toRenderBox(renderer)->isRelPositioned())
boundingBox.move(toRenderBox(renderer)->relativePositionLogicalOffset());
}
LayoutUnit offsetTop = renderer->containingBlock()->offsetFromLogicalTopOfFirstPage();
const LayoutPoint logicalOffsetFromTop(isHorizontalWritingMode() ? LayoutUnit() : offsetTop,
isHorizontalWritingMode() ? offsetTop : LayoutUnit());
boundingBox.moveBy(logicalOffsetFromTop);
LayoutUnit logicalTopForRenderer = region->logicalTopOfFlowThreadContentRect(boundingBox);
LayoutUnit logicalBottomForRenderer = region->logicalBottomOfFlowThreadContentRect(boundingBox);
// if the bounding box of the current element doesn't intersect the region box
// close the current range only if the start element began inside the region,
// otherwise just move the start position after this node and keep skipping them until we found a proper start position.
if (!boxIntersectsRegion(logicalTopForRenderer, logicalBottomForRenderer, logicalTopForRegion, logicalBottomForRegion)) {
if (foundStartPosition) {
if (!startsAboveRegion) {
if (range->intersectsNode(node, IGNORE_EXCEPTION))
range->setEndBefore(node, IGNORE_EXCEPTION);
rangeObjects.append(range->cloneRange(IGNORE_EXCEPTION));
range = Range::create(&contentElement->document());
startsAboveRegion = true;
} else
skipOverOutsideNodes = true;
}
if (skipOverOutsideNodes)
range->setStartAfter(node, IGNORE_EXCEPTION);
foundStartPosition = false;
continue;
}
// start position
if (logicalTopForRenderer < logicalTopForRegion && startsAboveRegion) {
if (renderer->isText()) { // Text crosses region top
// for Text elements, just find the last textbox that is contained inside the region and use its start() offset as start position
RenderText* textRenderer = toRenderText(renderer);
for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
if (offsetTop + box->logicalBottom() < logicalTopForRegion)
continue;
range->setStart(Position(toText(node), box->start()));
startsAboveRegion = false;
break;
}
} else { // node crosses region top
// for all elements, except Text, just set the start position to be before their children
startsAboveRegion = true;
range->setStart(Position(node, Position::PositionIsBeforeChildren));
}
} else { // node starts inside region
//.........这里部分代码省略.........
示例12: getParentOfFirstLineBox
static RenderObject* getParentOfFirstLineBox(RenderBlock* 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() && (!currChild->isInlineFlow() || curr->generatesLineBoxesForInlineChild(currChild)))
return curr;
if (currChild->isFloating() || currChild->isPositioned())
continue;
if (currChild->isTable() || !currChild->isRenderBlock())
break;
if (curr->isListItem() && currChild->style()->htmlHacks() && currChild->element() &&
(currChild->element()->hasTagName(ulTag)|| currChild->element()->hasTagName(olTag)))
break;
RenderObject* lineBox = getParentOfFirstLineBox(static_cast<RenderBlock*>(currChild), marker);
if (lineBox)
return lineBox;
}
return 0;
}
示例13: containsOnlyWhitespace
bool Text::textRendererIsNeeded(const NodeRenderingContext& context)
{
if (isEditingText())
return true;
if (!length())
return false;
if (context.style()->display() == NONE)
return false;
bool onlyWS = containsOnlyWhitespace();
if (!onlyWS)
return true;
RenderObject* parent = context.parentRenderer();
if (parent->isTable() || parent->isTableRow() || parent->isTableSection() || parent->isRenderTableCol() || parent->isFrameSet())
return false;
if (context.style()->preserveNewline()) // pre/pre-wrap/pre-line always make renderers.
return true;
RenderObject* prev = context.previousRenderer();
if (prev && prev->isBR()) // <span><br/> <br/></span>
return false;
if (parent->isRenderInline()) {
// <span><div/> <div/></span>
if (prev && !prev->isInline())
return false;
} else {
if (parent->isRenderBlock() && !parent->childrenInline() && (!prev || !prev->isInline()))
return false;
RenderObject* first = parent->firstChild();
while (first && first->isFloatingOrOutOfFlowPositioned())
first = first->nextSibling();
if (!first || context.nextRenderer() == first) {
// Whitespace at the start of a block just goes away. Don't even
// make a render object for this text.
return false;
}
}
return true;
}
示例14: caretMinOffset
int caretMinOffset(const Node* n)
{
RenderObject* r = n->renderer();
ASSERT(!n->isCharacterDataNode() || !r || r->isText()); // FIXME: This was a runtime check that seemingly couldn't fail; changed it to an assertion for now.
return r ? r->caretMinOffset() : 0;
}
示例15: cloneInline
void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
RenderBlock* middleBlock,
RenderObject* beforeChild, RenderFlow* oldCont)
{
// Create a clone of this inline.
RenderInline* clone = cloneInline(this);
clone->setContinuation(oldCont);
// Now take all of the children from beforeChild to the end and remove
// them from |this| and place them in the clone.
RenderObject* o = beforeChild;
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
clone->addChildToFlow(removeChildNode(tmp), 0);
tmp->setNeedsLayoutAndPrefWidthsRecalc();
}
// Hook |clone| up as the continuation of the middle block.
middleBlock->setContinuation(clone);
// We have been reparented and are now under the fromBlock. We need
// to walk up our inline parent chain until we hit the containing block.
// Once we hit the containing block we're done.
RenderFlow* curr = static_cast<RenderFlow*>(parent());
RenderFlow* currChild = this;
// FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone.
// There will eventually be a better approach to this problem that will let us nest to a much
// greater depth (see bugzilla bug 13430) but for now we have a limit. This *will* result in
// incorrect rendering, but the alternative is to hang forever.
unsigned splitDepth = 1;
const unsigned cMaxSplitDepth = 200;
while (curr && curr != fromBlock) {
if (splitDepth < cMaxSplitDepth) {
// Create a new clone.
RenderInline* cloneChild = clone;
clone = cloneInline(curr);
// Insert our child clone as the first child.
clone->addChildToFlow(cloneChild, 0);
// Hook the clone up as a continuation of |curr|.
RenderFlow* oldCont = curr->continuation();
curr->setContinuation(clone);
clone->setContinuation(oldCont);
// Someone may have indirectly caused a <q> to split. When this happens, the :after content
// has to move into the inline continuation. Call updateBeforeAfterContent to ensure that the inline's :after
// content gets properly destroyed.
if (document()->usesBeforeAfterRules())
curr->updateBeforeAfterContent(RenderStyle::AFTER);
// Now we need to take all of the children starting from the first child
// *after* currChild and append them all to the clone.
o = currChild->nextSibling();
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
clone->addChildToFlow(curr->removeChildNode(tmp), 0);
tmp->setNeedsLayoutAndPrefWidthsRecalc();
}
}
// Keep walking up the chain.
currChild = curr;
curr = static_cast<RenderFlow*>(curr->parent());
splitDepth++;
}
// Now we are at the block level. We need to put the clone into the toBlock.
toBlock->appendChildNode(clone);
// Now take all the children after currChild and remove them from the fromBlock
// and put them in the toBlock.
o = currChild->nextSibling();
while (o) {
RenderObject* tmp = o;
o = tmp->nextSibling();
toBlock->appendChildNode(fromBlock->removeChildNode(tmp));
}
}