void RenderRubyBase::mergeBlockChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) { // This function removes all children that are before fromBeforeChild and appends them to toBase. ASSERT(!childrenInline()); ASSERT(toBase); ASSERT(!toBase->childrenInline()); // Quick check whether we have anything to do, to simplify the following code. if (fromBeforeChild != firstChild()) return; // If an anonymous block would be put next to another such block, then merge those. RenderObject* firstChildHere = firstChild(); RenderObject* lastChildThere = toBase->lastChild(); if (firstChildHere && firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) { RenderBlock* anonBlockHere = toRenderBlock(firstChildHere); RenderBlock* anonBlockThere = toRenderBlock(lastChildThere); anonBlockHere->moveAllChildrenTo(anonBlockThere, anonBlockThere->children()); anonBlockHere->deleteLineBoxTree(); anonBlockHere->destroy(); } // Move all remaining children normally. moveChildrenTo(toBase, firstChild(), fromBeforeChild); }
void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild) { ASSERT(!childrenInline()); ASSERT_ARG(toBase, toBase); if (!firstChild()) return; if (toBase->childrenInline()) toBase->makeChildrenNonInline(); // If an anonymous block would be put next to another such block, then merge those. RenderObject* firstChildHere = firstChild(); RenderObject* lastChildThere = toBase->lastChild(); if (firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) { RenderBlock* anonBlockHere = toRenderBlock(firstChildHere); RenderBlock* anonBlockThere = toRenderBlock(lastChildThere); anonBlockHere->moveAllChildrenTo(anonBlockThere, true); anonBlockHere->deleteLineBoxTree(); anonBlockHere->destroy(); } // Move all remaining children normally. moveChildrenTo(toBase, firstChild(), beforeChild); }
void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild) { ASSERT(childrenInline()); ASSERT_ARG(toBase, toBase); if (!firstChild()) return; RenderBlock* toBlock; if (toBase->childrenInline()) { // The standard and easy case: move the children into the target base toBlock = toBase; } else { // We need to wrap the inline objects into an anonymous block. // If toBase has a suitable block, we re-use it, otherwise create a new one. RenderObject* lastChild = toBase->lastChild(); if (lastChild && lastChild->isAnonymousBlock() && lastChild->childrenInline()) toBlock = toRenderBlock(lastChild); else { toBlock = toBase->createAnonymousBlock(); toBase->insertChildInternal(toBlock, nullptr, NotifyChildren); } } // Move our inline children into the target block we determined above. moveChildrenTo(toBlock, firstChild(), beforeChild); }
bool RenderRubyBase::hasOnlyWrappedInlineChildren(RenderObject* beforeChild) const { // Tests whether all children in the base before beforeChild are either floated/positioned, // or inline objects wrapped in anonymous blocks. // Note that beforeChild may be 0, in which case all children are looked at. for (RenderObject* child = firstChild(); child != beforeChild; child = child->nextSibling()) { if (!child->isFloatingOrPositioned() && !(child->isAnonymousBlock() && child->childrenInline())) return false; } return true; }
bool Text::textRendererIsNeeded(const RenderStyle& style, const RenderObject& parent) { if (!parent.canHaveChildren()) return false; if (isEditingText()) return true; if (!length()) return false; if (style.display() == NONE) return false; if (!containsOnlyWhitespace()) return true; if (!canHaveWhitespaceChildren(parent)) return false; if (style.preserveNewline()) // pre/pre-wrap/pre-line always make renderers. return true; const RenderObject* prev = NodeRenderingTraversal::previousSiblingRenderer(*this); 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; // Avoiding creation of a Renderer for the text node is a non-essential memory optimization. // So to avoid blowing up on very wide DOMs, we limit the number of siblings to visit. unsigned maxSiblingsToVisit = 50; RenderObject* first = parent.slowFirstChild(); while (first && first->isFloatingOrOutOfFlowPositioned() && maxSiblingsToVisit--) first = first->nextSibling(); if (!first || first == renderer() || NodeRenderingTraversal::nextSiblingRenderer(*this) == 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; }
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; }
bool TextImpl::rendererIsNeeded(RenderStyle *style) { if (!CharacterDataImpl::rendererIsNeeded(style)) { return false; } bool onlyWS = containsOnlyWhitespace(); if (!onlyWS) { return true; } RenderObject *par = parentNode()->renderer(); if (par->isTable() || par->isTableRow() || par->isTableSection()) { return false; } if (style->preserveWS() || style->preserveLF()) { return true; } RenderObject *prev = previousRenderer(); if (par->isInlineFlow()) { // <span><div/> <div/></span> if (prev && !prev->isInline()) { return false; } } else { if (par->isRenderBlock() && !par->childrenInline() && (!prev || !prev->isInline())) { return false; } RenderObject *first = par->firstChild(); while (first && first->isFloatingOrPositioned()) first = first->nextSibling(); RenderObject *next = nextRenderer(); if (!first || next == 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; }
bool Text::rendererIsNeeded(RenderStyle *style) { if (!CharacterData::rendererIsNeeded(style)) return false; bool onlyWS = containsOnlyWhitespace(); if (!onlyWS) return true; RenderObject *par = parentNode()->renderer(); if (par->isTable() || par->isTableRow() || par->isTableSection() || par->isTableCol() || par->isFrameSet()) return false; if (style->preserveNewline()) // pre/pre-wrap/pre-line always make renderers. return true; RenderObject *prev = previousRenderer(); if (prev && prev->isBR()) // <span><br/> <br/></span> return false; if (par->isInlineFlow()) { // <span><div/> <div/></span> if (prev && !prev->isInline()) return false; } else { if (par->isRenderBlock() && !par->childrenInline() && (!prev || !prev->isInline())) return false; RenderObject *first = par->firstChild(); while (first && first->isFloatingOrPositioned()) first = first->nextSibling(); RenderObject *next = nextRenderer(); if (!first || next == 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; }
void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* fromBeforeChild) { RenderBlock* toBlock; if (toBase->childrenInline()) { // The standard and easy case: move the children into the target base toBlock = toBase; } else { // We need to wrap the inline objects into an anonymous block. // If toBase has a suitable block, we re-use it, otherwise create a new one. RenderObject* lastChild = toBase->lastChild(); if (lastChild && lastChild->isAnonymousBlock() && lastChild->childrenInline()) toBlock = toRenderBlock(lastChild); else { toBlock = toBase->createAnonymousBlock(); toBase->children()->appendChildNode(toBase, toBlock); } } // Move our inline children into the target block we determined above. moveChildrenTo(toBlock, firstChild(), fromBeforeChild); }
static bool textRendererIsNeeded(const Text& textNode, const RenderObject& parentRenderer, const RenderStyle& style) { if (textNode.isEditingText()) return true; if (!textNode.length()) return false; if (style.display() == NONE) return false; if (!textNode.containsOnlyWhitespace()) return true; // This text node has nothing but white space. We may still need a renderer in some cases. if (parentRenderer.isTable() || parentRenderer.isTableRow() || parentRenderer.isTableSection() || parentRenderer.isRenderTableCol() || parentRenderer.isFrameSet()) return false; if (style.preserveNewline()) // pre/pre-wrap/pre-line always make renderers. return true; RenderObject* previousRenderer = previousSiblingRenderer(textNode); if (previousRenderer && previousRenderer->isBR()) // <span><br/> <br/></span> return false; if (parentRenderer.isRenderInline()) { // <span><div/> <div/></span> if (previousRenderer && !previousRenderer->isInline()) return false; } else { if (parentRenderer.isRenderBlock() && !parentRenderer.childrenInline() && (!previousRenderer || !previousRenderer->isInline())) return false; RenderObject* first = parentRenderer.firstChild(); while (first && first->isFloatingOrOutOfFlowPositioned()) first = first->nextSibling(); RenderObject* nextRenderer = nextSiblingRenderer(textNode); if (!first || 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; }
void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject) { // Double check that the document did in fact use generated content rules. Otherwise we should not have been called. ASSERT(owner->document()->usesBeforeAfterRules()); // In CSS2, before/after pseudo-content cannot nest. Check this first. if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER) return; if (!styledObject) styledObject = owner; RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type); RenderObject* child; switch (type) { case BEFORE: child = beforePseudoElementRenderer(owner); break; case AFTER: child = afterPseudoElementRenderer(owner); break; default: ASSERT_NOT_REACHED(); return; } // Whether or not we currently have generated content attached. bool oldContentPresent = child; // Whether or not we now want generated content. bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE; // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate // :after content and not :before content. if (newContentWanted && type == BEFORE && owner->isElementContinuation()) newContentWanted = false; // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object, // then we don't generate the :after content. if (newContentWanted && type == AFTER && owner->virtualContinuation()) newContentWanted = false; // If we don't want generated content any longer, or if we have generated content, but it's no longer // identical to the new content data we want to build render objects for, then we nuke all // of the old generated content. if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle, owner->document()) == Node::Detach)) { // Nuke the child. if (child->style()->styleType() == type) { oldContentPresent = false; child->destroy(); child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild(); } } // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we // have no generated content and can now return. if (!newContentWanted) return; if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && !pseudoElementStyle->isFloating() && !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition)) // According to the CSS2 spec (the end of section 12.1), the only allowed // display values for the pseudo style are NONE and INLINE for inline flows. // FIXME: CSS2.1 lifted this restriction, but block display types will crash. // For now we at least relax the restriction to allow all inline types like inline-block // and inline-table. pseudoElementStyle->setDisplay(INLINE); if (oldContentPresent) { updateBeforeAfterStyle(child, type, pseudoElementStyle); return; // We've updated the generated content. That's all we needed to do. } RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0; if (insertBefore && insertBefore->isAnonymousBlock() && insertBefore->childrenInline() && !insertBefore->isEmpty()) { // We are going to add the "before" element. We have to check whether the "insertBefore" element // is an anonymous block with inline children. If it is, then we should insert the "before" element // before the first inline child of the anonymous block, otherwise we will end up with the "before" // element in a different block. We do this only when the anonymous block has children, otherwise // we end up with the before element in a wrong block. insertBefore = insertBefore->firstChild(); } // Nothing goes before the intruded run-in, not even generated content. if (insertBefore && insertBefore->isRunIn() && owner->isRenderBlock() && toRenderBlock(owner)->runInIsPlacedIntoSiblingBlock(insertBefore)) insertBefore = insertBefore->nextSibling(); // Generated content consists of a single container that houses multiple children (specified // by the content property). This generated content container gets the pseudo-element style set on it. RenderObject* generatedContentContainer = 0; // Walk our list of generated content and create render objects for each. for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) { RenderObject* renderer = createRendererForBeforeAfterContent(owner, content, pseudoElementStyle); if (renderer) { if (!generatedContentContainer) { // Make a generated box that might be any display type now that we are able to drill down into children // to find the original content properly. generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle); ASSERT(styledObject->node()); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements. generatedContentContainer->setNode(styledObject->node()); // This allows access to the generatingNode. generatedContentContainer->setStyle(pseudoElementStyle); if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) { // The generated content container is not allowed here -> abort. generatedContentContainer->destroy(); renderer->destroy(); return; } // When we don't have a first child and are part of a continuation chain, // insertBefore is incorrectly set to zero above, which causes the :before // child to end up at the end of continuation chain. // See https://bugs.webkit.org/show_bug.cgi?id=78380. if (!insertBefore && type == BEFORE && owner->virtualContinuation()) owner->addChildIgnoringContinuation(generatedContentContainer, 0); else owner->addChild(generatedContentContainer, insertBefore); } if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle)) generatedContentContainer->addChild(renderer); else renderer->destroy(); } } if (!generatedContentContainer) return; // Handle placement of run-ins. We do the run-in placement at the end since generatedContentContainer can get destroyed. RenderObject* generatedContentContainerImmediateParent = generatedContentContainer->parent(); if (generatedContentContainerImmediateParent->isRenderBlock()) toRenderBlock(generatedContentContainerImmediateParent)->placeRunInIfNeeded(generatedContentContainer, PlaceGeneratedRunIn); }
static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject) { guint16 interfaceMask = 0; // Component interface is always supported interfaceMask |= 1 << WAI_COMPONENT; AccessibilityRole role = coreObject->roleValue(); // Action // As the implementation of the AtkAction interface is a very // basic one (just relays in executing the default action for each // object, and only supports having one action per object), it is // better just to implement this interface for every instance of // the WebKitAccessible class and let WebCore decide what to do. interfaceMask |= 1 << WAI_ACTION; // Selection if (coreObject->isListBox() || coreObject->isMenuList()) interfaceMask |= 1 << WAI_SELECTION; // Get renderer if available. RenderObject* renderer = 0; if (coreObject->isAccessibilityRenderObject()) renderer = coreObject->renderer(); // Hyperlink (links and embedded objects). if (coreObject->isLink() || (renderer && renderer->isReplaced())) interfaceMask |= 1 << WAI_HYPERLINK; // Text & Editable Text if (role == StaticTextRole || coreObject->isMenuListOption()) interfaceMask |= 1 << WAI_TEXT; else { if (coreObject->isTextControl()) { interfaceMask |= 1 << WAI_TEXT; if (!coreObject->isReadOnly()) interfaceMask |= 1 << WAI_EDITABLE_TEXT; } else { if (role != TableRole) { interfaceMask |= 1 << WAI_HYPERTEXT; if ((renderer && renderer->childrenInline()) || roleIsTextType(role)) interfaceMask |= 1 << WAI_TEXT; } // Add the TEXT interface for list items whose // first accessible child has a text renderer if (role == ListItemRole) { AccessibilityObject::AccessibilityChildrenVector children = coreObject->children(); if (children.size()) { AccessibilityObject* axRenderChild = children.at(0).get(); interfaceMask |= getInterfaceMaskFromObject(axRenderChild); } } } } // Image if (coreObject->isImage()) interfaceMask |= 1 << WAI_IMAGE; // Table if (role == TableRole) interfaceMask |= 1 << WAI_TABLE; // Document if (role == WebAreaRole) interfaceMask |= 1 << WAI_DOCUMENT; // Value if (role == SliderRole || role == SpinButtonRole || role == ScrollBarRole || role == ProgressIndicatorRole) interfaceMask |= 1 << WAI_VALUE; #if ENABLE(INPUT_TYPE_COLOR) // Color type. if (role == ColorWellRole) interfaceMask |= 1 << WAI_TEXT; #endif return interfaceMask; }
void RenderContainer::removeLeftoverAnonymousBoxes() { // we have to go over all child nodes and remove anonymous boxes, that do _not_ // have inline children to keep the tree flat RenderObject *child = firstChild(); while( child ) { RenderObject *next = child->nextSibling(); if ( child->isRenderBlock() && child->isAnonymousBlock() && !child->continuation() && !child->childrenInline() && !child->isTableCell() ) { RenderObject *firstAnChild = child->firstChild(); RenderObject *lastAnChild = child->lastChild(); if ( firstAnChild ) { RenderObject *o = firstAnChild; while( o ) { o->setParent( this ); o = o->nextSibling(); } firstAnChild->setPreviousSibling( child->previousSibling() ); lastAnChild->setNextSibling( child->nextSibling() ); if ( child->previousSibling() ) child->previousSibling()->setNextSibling( firstAnChild ); if ( child->nextSibling() ) child->nextSibling()->setPreviousSibling( lastAnChild ); } else { if ( child->previousSibling() ) child->previousSibling()->setNextSibling( child->nextSibling() ); if ( child->nextSibling() ) child->nextSibling()->setPreviousSibling( child->previousSibling() ); } if ( child == firstChild() ) m_first = firstAnChild; if ( child == lastChild() ) m_last = lastAnChild; child->setParent( 0 ); child->setPreviousSibling( 0 ); child->setNextSibling( 0 ); if ( !child->isText() ) { RenderContainer *c = static_cast<RenderContainer *>(child); c->m_first = 0; c->m_next = 0; } child->detach(); } child = next; } if ( parent() ) parent()->removeLeftoverAnonymousBoxes(); }
void RenderObjectChildList::updateBeforeAfterContent(RenderObject* owner, PseudoId type, const RenderObject* styledObject) { // Double check that the document did in fact use generated content rules. Otherwise we should not have been called. ASSERT(owner->document()->usesBeforeAfterRules()); // In CSS2, before/after pseudo-content cannot nest. Check this first. if (owner->style()->styleType() == BEFORE || owner->style()->styleType() == AFTER) return; if (!styledObject) styledObject = owner; RenderStyle* pseudoElementStyle = styledObject->getCachedPseudoStyle(type); RenderObject* child; switch (type) { case BEFORE: child = beforePseudoElementRenderer(owner); break; case AFTER: child = afterPseudoElementRenderer(owner); break; default: ASSERT_NOT_REACHED(); return; } // Whether or not we currently have generated content attached. bool oldContentPresent = child; // Whether or not we now want generated content. bool newContentWanted = pseudoElementStyle && pseudoElementStyle->display() != NONE; // For <q><p/></q>, if this object is the inline continuation of the <q>, we only want to generate // :after content and not :before content. if (newContentWanted && type == BEFORE && owner->isElementContinuation()) newContentWanted = false; // Similarly, if we're the beginning of a <q>, and there's an inline continuation for our object, // then we don't generate the :after content. if (newContentWanted && type == AFTER && owner->virtualContinuation()) newContentWanted = false; // If we don't want generated content any longer, or if we have generated content, but it's no longer // identical to the new content data we want to build render objects for, then we nuke all // of the old generated content. if (oldContentPresent && (!newContentWanted || Node::diff(child->style(), pseudoElementStyle) == Node::Detach)) { // Nuke the child. if (child->style()->styleType() == type) { oldContentPresent = false; child->destroy(); child = (type == BEFORE) ? owner->virtualChildren()->firstChild() : owner->virtualChildren()->lastChild(); } } // If we have no pseudo-element style or if the pseudo-element style's display type is NONE, then we // have no generated content and can now return. if (!newContentWanted) return; if (owner->isRenderInline() && !pseudoElementStyle->isDisplayInlineType() && !pseudoElementStyle->isFloating() && !(pseudoElementStyle->position() == AbsolutePosition || pseudoElementStyle->position() == FixedPosition)) // According to the CSS2 spec (the end of section 12.1), the only allowed // display values for the pseudo style are NONE and INLINE for inline flows. // FIXME: CSS2.1 lifted this restriction, but block display types will crash. // For now we at least relax the restriction to allow all inline types like inline-block // and inline-table. pseudoElementStyle->setDisplay(INLINE); if (oldContentPresent) { if (child && child->style()->styleType() == type) { // We have generated content present still. We want to walk this content and update our // style information with the new pseudo-element style. child->setStyle(pseudoElementStyle); RenderObject* beforeAfterParent = findBeforeAfterParent(child); if (!beforeAfterParent) return; // When beforeAfterParent is not equal to child (e.g. in tables), // we need to create new styles inheriting from pseudoElementStyle // on all the intermediate parents (leaving their display same). if (beforeAfterParent != child) { RenderObject* curr = beforeAfterParent; while (curr && curr != child) { ASSERT(curr->isAnonymous()); RefPtr<RenderStyle> newStyle = RenderStyle::create(); newStyle->inheritFrom(pseudoElementStyle); newStyle->setDisplay(curr->style()->display()); newStyle->setStyleType(curr->style()->styleType()); curr->setStyle(newStyle); curr = curr->parent(); } } // Note that if we ever support additional types of generated content (which should be way off // in the future), this code will need to be patched. for (RenderObject* genChild = beforeAfterParent->firstChild(); genChild; genChild = genChild->nextSibling()) { if (genChild->isText()) // Generated text content is a child whose style also needs to be set to the pseudo-element style. genChild->setStyle(pseudoElementStyle); else if (genChild->isImage()) { // Images get an empty style that inherits from the pseudo. RefPtr<RenderStyle> style = RenderStyle::create(); style->inheritFrom(pseudoElementStyle); genChild->setStyle(style.release()); } else { // RenderListItem may insert a list marker here. We do not need to care about this case. // Otherwise, genChild must be a first-letter container. updateFirstLetter() will take care of it. ASSERT(genChild->isListMarker() || genChild->style()->styleType() == FIRST_LETTER); } } } return; // We've updated the generated content. That's all we needed to do. } RenderObject* insertBefore = (type == BEFORE) ? owner->virtualChildren()->firstChild() : 0; if (insertBefore && insertBefore->isAnonymousBlock() && insertBefore->childrenInline() && !insertBefore->isEmpty()) { // We are going to add the "before" element. We have to check whether the "insertBefore" element // is an anonymous block with inline children. If it is, then we should insert the "before" element // before the first inline child of the anonymous block, otherwise we will end up with the "before" // element in a different block. We do this only when the anonymous block has children, otherwise // we end up with the before element in a wrong block. insertBefore = insertBefore->firstChild(); } // Generated content consists of a single container that houses multiple children (specified // by the content property). This generated content container gets the pseudo-element style set on it. RenderObject* generatedContentContainer = 0; // Walk our list of generated content and create render objects for each. for (const ContentData* content = pseudoElementStyle->contentData(); content; content = content->next()) { RenderObject* renderer = 0; switch (content->type()) { case CONTENT_NONE: break; case CONTENT_TEXT: renderer = new (owner->renderArena()) RenderTextFragment(owner->document() /* anonymous object */, static_cast<const TextContentData*>(content)->text().impl()); renderer->setStyle(pseudoElementStyle); break; case CONTENT_OBJECT: { RenderImage* image = new (owner->renderArena()) RenderImage(owner->document()); // anonymous object RefPtr<RenderStyle> style = RenderStyle::create(); style->inheritFrom(pseudoElementStyle); image->setStyle(style.release()); if (const StyleImage* styleImage = static_cast<const ImageContentData*>(content)->image()) image->setImageResource(RenderImageResourceStyleImage::create(const_cast<StyleImage*>(styleImage))); else image->setImageResource(RenderImageResource::create()); renderer = image; break; } case CONTENT_COUNTER: renderer = new (owner->renderArena()) RenderCounter(owner->document(), *static_cast<const CounterContentData*>(content)->counter()); renderer->setStyle(pseudoElementStyle); break; case CONTENT_QUOTE: renderer = new (owner->renderArena()) RenderQuote(owner->document(), static_cast<const QuoteContentData*>(content)->quote()); renderer->setStyle(pseudoElementStyle); break; } if (renderer) { if (!generatedContentContainer) { // Make a generated box that might be any display type now that we are able to drill down into children // to find the original content properly. generatedContentContainer = RenderObject::createObject(owner->document(), pseudoElementStyle); ASSERT(styledObject->node()); // The styled object cannot be anonymous or else it could not have ':before' or ':after' pseudo elements. generatedContentContainer->setNode(styledObject->node()); // This allows access to the generatingNode. generatedContentContainer->setStyle(pseudoElementStyle); if (!owner->isChildAllowed(generatedContentContainer, pseudoElementStyle)) { // The generated content container is not allowed here -> abort. generatedContentContainer->destroy(); renderer->destroy(); return; } owner->addChild(generatedContentContainer, insertBefore); } if (generatedContentContainer->isChildAllowed(renderer, pseudoElementStyle)) generatedContentContainer->addChild(renderer); else renderer->destroy(); } } }
static guint16 getInterfaceMaskFromObject(AccessibilityObject* coreObject) { guint16 interfaceMask = 0; // Component interface is always supported interfaceMask |= 1 << WAIComponent; AccessibilityRole role = coreObject->roleValue(); // Action // As the implementation of the AtkAction interface is a very // basic one (just relays in executing the default action for each // object, and only supports having one action per object), it is // better just to implement this interface for every instance of // the WebKitAccessible class and let WebCore decide what to do. interfaceMask |= 1 << WAIAction; // Selection if (coreObject->isListBox() || coreObject->isMenuList()) interfaceMask |= 1 << WAISelection; // Get renderer if available. RenderObject* renderer = nullptr; if (coreObject->isAccessibilityRenderObject()) renderer = coreObject->renderer(); // Hyperlink (links and embedded objects). if (coreObject->isLink() || (renderer && renderer->isReplaced())) interfaceMask |= 1 << WAIHyperlink; // Text, Editable Text & Hypertext if (role == StaticTextRole || coreObject->isMenuListOption()) interfaceMask |= 1 << WAIText; else if (coreObject->isTextControl()) { interfaceMask |= 1 << WAIText; if (!coreObject->isReadOnly()) interfaceMask |= 1 << WAIEditableText; } else if (!coreObject->isWebArea()) { if (role != TableRole) { interfaceMask |= 1 << WAIHypertext; if ((renderer && renderer->childrenInline()) || roleIsTextType(role) || coreObject->isMathToken()) interfaceMask |= 1 << WAIText; } // Add the TEXT interface for list items whose // first accessible child has a text renderer if (role == ListItemRole) { const AccessibilityObject::AccessibilityChildrenVector& children = coreObject->children(); if (children.size()) { AccessibilityObject* axRenderChild = children.at(0).get(); interfaceMask |= getInterfaceMaskFromObject(axRenderChild); } } } // Image if (coreObject->isImage()) interfaceMask |= 1 << WAIImage; // Table if (role == TableRole || role == GridRole) interfaceMask |= 1 << WAITable; #if ATK_CHECK_VERSION(2,11,90) if (role == CellRole || role == ColumnHeaderRole || role == RowHeaderRole) interfaceMask |= 1 << WAITableCell; #endif // Document if (role == WebAreaRole) interfaceMask |= 1 << WAIDocument; // Value if (role == SliderRole || role == SpinButtonRole || role == ScrollBarRole || role == ProgressIndicatorRole) interfaceMask |= 1 << WAIValue; #if ENABLE(INPUT_TYPE_COLOR) // Color type. if (role == ColorWellRole) interfaceMask |= 1 << WAIText; #endif return interfaceMask; }