⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 applystylecommand.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        if (before ? n->previousSibling() : n->nextSibling())            splitElement(parent, before ? n : n->nextSibling());        if (parent == highestAncestorWithUnicodeBidi)            break;        n = n->parent();    }    return unsplitAncestor;}void ApplyStyleCommand::removeEmbeddingUpToEnclosingBlock(Node* node, Node* unsplitAncestor){    Node* block = enclosingBlock(node);    if (!block)        return;    Node* n = node->parent();    while (n != block && n != unsplitAncestor) {        Node* parent = n->parent();        if (!n->isStyledElement()) {            n = parent;            continue;        }        StyledElement* element = static_cast<StyledElement*>(n);        RefPtr<CSSValue> unicodeBidi = computedStyle(element)->getPropertyCSSValue(CSSPropertyUnicodeBidi);        if (unicodeBidi) {            ASSERT(unicodeBidi->isPrimitiveValue());            if (static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent() != CSSValueNormal) {                // FIXME: This code should really consider the mapped attribute 'dir', the inline style declaration,                // and all matching style rules in order to determine how to best set the unicode-bidi property to 'normal'.                // For now, it assumes that if the 'dir' attribute is present, then removing it will suffice, and                // otherwise it sets the property in the inline style declaration.                if (element->hasAttribute(dirAttr)) {                    // FIXME: If this is a BDO element, we should probably just remove it if it has no                    // other attributes, like we (should) do with B and I elements.                    removeNodeAttribute(element, dirAttr);                } else {                    RefPtr<CSSMutableStyleDeclaration> inlineStyle = element->getInlineStyleDecl()->copy();                    inlineStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueNormal);                    inlineStyle->removeProperty(CSSPropertyDirection);                    setNodeAttribute(element, styleAttr, inlineStyle->cssText());                    // FIXME: should this be isSpanWithoutAttributesOrUnstyleStyleSpan?  Need a test.                    if (isUnstyledStyleSpan(element))                        removeNodePreservingChildren(element);                }            }        }        n = parent;    }}void ApplyStyleCommand::applyInlineStyle(CSSMutableStyleDeclaration *style){    Node* startDummySpanAncestor = 0;    Node* endDummySpanAncestor = 0;        // update document layout once before removing styles    // so that we avoid the expense of updating before each and every call    // to check a computed style    updateLayout();    // adjust to the positions we want to use for applying style    Position start = startPosition();    Position end = endPosition();    if (Range::compareBoundaryPoints(end, start) < 0) {        Position swap = start;        start = end;        end = swap;    }    // split the start node and containing element if the selection starts inside of it    bool splitStart = splitTextElementAtStartIfNeeded(start, end);     if (splitStart) {        start = startPosition();        end = endPosition();        startDummySpanAncestor = dummySpanAncestorForNode(start.node());    }    // split the end node and containing element if the selection ends inside of it    bool splitEnd = splitTextElementAtEndIfNeeded(start, end);    if (splitEnd) {        start = startPosition();        end = endPosition();        endDummySpanAncestor = dummySpanAncestorForNode(end.node());    }    RefPtr<CSSValue> unicodeBidi = style->getPropertyCSSValue(CSSPropertyUnicodeBidi);    RefPtr<CSSValue> direction;    HTMLElement* startUnsplitAncestor = 0;    HTMLElement* endUnsplitAncestor = 0;    if (unicodeBidi) {        RefPtr<CSSPrimitiveValue> allowedDirection;        ASSERT(unicodeBidi->isPrimitiveValue());        if (static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent() == CSSValueEmbed) {            // Leave alone an ancestor that provides the desired single level embedding, if there is one.            direction = style->getPropertyCSSValue(CSSPropertyDirection);            ASSERT(direction->isPrimitiveValue());            allowedDirection = static_cast<CSSPrimitiveValue*>(direction.get());        }        startUnsplitAncestor = splitAncestorsWithUnicodeBidi(start.node(), true, allowedDirection);        endUnsplitAncestor = splitAncestorsWithUnicodeBidi(end.node(), false, allowedDirection);        removeEmbeddingUpToEnclosingBlock(start.node(), startUnsplitAncestor);        removeEmbeddingUpToEnclosingBlock(end.node(), endUnsplitAncestor);    }    // Remove style from the selection.    // Use the upstream position of the start for removing style.    // This will ensure we remove all traces of the relevant styles from the selection    // and prevent us from adding redundant ones, as described in:    // <rdar://problem/3724344> Bolding and unbolding creates extraneous tags    Position removeStart = start.upstream();    Position embeddingRemoveStart = removeStart;    Position embeddingRemoveEnd = end;    if (unicodeBidi) {        // Avoid removing the dir attribute and the unicode-bidi and direction properties from the unsplit ancestors.        if (startUnsplitAncestor && nodeFullySelected(startUnsplitAncestor, removeStart, end))            embeddingRemoveStart = positionAfterNode(startUnsplitAncestor);        if (endUnsplitAncestor && nodeFullySelected(endUnsplitAncestor, removeStart, end))            embeddingRemoveEnd = positionBeforeNode(endUnsplitAncestor).downstream();    }    if (embeddingRemoveStart != removeStart || embeddingRemoveEnd != end) {        RefPtr<CSSMutableStyleDeclaration> embeddingStyle = CSSMutableStyleDeclaration::create();        embeddingStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueEmbed);        embeddingStyle->setProperty(CSSPropertyDirection, static_cast<CSSPrimitiveValue*>(direction.get())->getIdent());        if (Range::compareBoundaryPoints(embeddingRemoveStart, embeddingRemoveEnd) <= 0)            removeInlineStyle(embeddingStyle, embeddingRemoveStart, embeddingRemoveEnd);        RefPtr<CSSMutableStyleDeclaration> styleWithoutEmbedding = style->copy();        styleWithoutEmbedding->removeProperty(CSSPropertyUnicodeBidi);        styleWithoutEmbedding->removeProperty(CSSPropertyDirection);        removeInlineStyle(styleWithoutEmbedding, removeStart, end);   } else        removeInlineStyle(style, removeStart, end);    start = startPosition();    end = endPosition();    if (splitStart) {        bool mergedStart = mergeStartWithPreviousIfIdentical(start, end);        if (mergedStart) {            start = startPosition();            end = endPosition();        }    }    if (splitEnd) {        mergeEndWithNextIfIdentical(start, end);        start = startPosition();        end = endPosition();    }    // update document layout once before running the rest of the function    // so that we avoid the expense of updating before each and every call    // to check a computed style    updateLayout();    Position embeddingApplyStart = start;    Position embeddingApplyEnd = end;    if (unicodeBidi) {        // Avoid applying the unicode-bidi and direction properties beneath ancestors that already have them.        Node* startEnclosingBlock = enclosingBlock(start.node());        for (Node* n = start.node(); n != startEnclosingBlock; n = n->parent()) {            if (n->isHTMLElement()) {                RefPtr<CSSValue> ancestorUnicodeBidi = computedStyle(n)->getPropertyCSSValue(CSSPropertyUnicodeBidi);                if (ancestorUnicodeBidi) {                    ASSERT(ancestorUnicodeBidi->isPrimitiveValue());                    if (static_cast<CSSPrimitiveValue*>(ancestorUnicodeBidi.get())->getIdent() == CSSValueEmbed) {                        embeddingApplyStart = positionAfterNode(n);                        break;                    }                }            }        }        Node* endEnclosingBlock = enclosingBlock(end.node());        for (Node* n = end.node(); n != endEnclosingBlock; n = n->parent()) {            if (n->isHTMLElement()) {                RefPtr<CSSValue> ancestorUnicodeBidi = computedStyle(n)->getPropertyCSSValue(CSSPropertyUnicodeBidi);                if (ancestorUnicodeBidi) {                    ASSERT(ancestorUnicodeBidi->isPrimitiveValue());                    if (static_cast<CSSPrimitiveValue*>(ancestorUnicodeBidi.get())->getIdent() == CSSValueEmbed) {                        embeddingApplyEnd = positionBeforeNode(n);                        break;                    }                }            }        }    }    if (embeddingApplyStart != start || embeddingApplyEnd != end) {        if (embeddingApplyStart.isNotNull() && embeddingApplyEnd.isNotNull()) {            RefPtr<CSSMutableStyleDeclaration> embeddingStyle = CSSMutableStyleDeclaration::create();            embeddingStyle->setProperty(CSSPropertyUnicodeBidi, CSSValueEmbed);            embeddingStyle->setProperty(CSSPropertyDirection, static_cast<CSSPrimitiveValue*>(direction.get())->getIdent());            applyInlineStyleToRange(embeddingStyle.get(), embeddingApplyStart, embeddingApplyEnd);        }        RefPtr<CSSMutableStyleDeclaration> styleWithoutEmbedding = style->copy();        styleWithoutEmbedding->removeProperty(CSSPropertyUnicodeBidi);        styleWithoutEmbedding->removeProperty(CSSPropertyDirection);        applyInlineStyleToRange(styleWithoutEmbedding.get(), start, end);   } else        applyInlineStyleToRange(style, start, end);    // Remove dummy style spans created by splitting text elements.    cleanupUnstyledAppleStyleSpans(startDummySpanAncestor);    if (endDummySpanAncestor != startDummySpanAncestor)        cleanupUnstyledAppleStyleSpans(endDummySpanAncestor);}void ApplyStyleCommand::applyInlineStyleToRange(CSSMutableStyleDeclaration* style, const Position& start, const Position& rangeEnd){    Node* node = start.node();    Position end = rangeEnd;    bool rangeIsEmpty = false;    if (start.offset() >= caretMaxOffset(start.node())) {        node = node->traverseNextNode();        Position newStart = Position(node, 0);        if (Range::compareBoundaryPoints(end, newStart) < 0)            rangeIsEmpty = true;    }    if (!rangeIsEmpty) {        // pastEndNode is the node after the last fully selected node.        Node* pastEndNode = end.node();        if (end.offset() >= caretMaxOffset(end.node()))            pastEndNode = end.node()->traverseNextSibling();        // FIXME: Callers should perform this operation on a Range that includes the br        // if they want style applied to the empty line.        if (start == end && start.node()->hasTagName(brTag))            pastEndNode = start.node()->traverseNextNode();        // Add the style to selected inline runs.        for (Node* next; node && node != pastEndNode; node = next) {                        next = node->traverseNextNode();                        if (!node->renderer() || !node->isContentEditable())                continue;                        if (!node->isContentRichlyEditable() && node->isHTMLElement()) {                // This is a plaintext-only region. Only proceed if it's fully selected.                // pastEndNode is the node after the last fully selected node, so if it's inside node then                // node isn't fully selected.                if (pastEndNode->isDescendantOf(node))                    break;                // Add to this element's inline style and skip over its contents.                HTMLElement* element = static_cast<HTMLElement*>(node);                RefPtr<CSSMutableStyleDeclaration> inlineStyle = element->getInlineStyleDecl()->copy();                inlineStyle->merge(style);                setNodeAttribute(element, styleAttr, inlineStyle->cssText());                next = node->traverseNextSibling();                continue;            }                    if (isBlock(node))                continue;                            if (node->childNodeCount()) {                if (editingIgnoresContent(node)) {                    next = node->traverseNextSibling();                    continue;                }                continue;            }                        Node* runStart = node;            // Find the end of the run.            Node* sibling = node->nextSibling();            while (sibling && sibling != pastEndNode && (!sibling->isElementNode() || sibling->hasTagName(brTag)) && !isBlock(sibling)) {                node = sibling;                sibling = node->nextSibling();            }            // Recompute next, since node has changed.            next = node->traverseNextNode();            // Apply the style to the run.            addInlineStyleIfNeeded(style, runStart, node);        }    }}// This function maps from styling tags to CSS styles.  Used for knowing which// styling tags should be removed when toggling styles.bool ApplyStyleCommand::isHTMLStyleNode(CSSMutableStyleDeclaration* style, HTMLElement* elem){    CSSMutableStyleDeclaration::const_iterator end = style->end();    for (CSSMutableStyleDeclaration::const_iterator it = style->begin(); it != end; ++it) {        switch ((*it).id()) {        case CSSPropertyFontWeight:            // IE inserts "strong" tags for execCommand("bold"), so we remove them, even though they're not strictly presentational            if (elem->hasLocalName(bTag) || elem->hasLocalName(strongTag))                return true;            break;        case CSSPropertyVerticalAlign:            if (elem->hasLocalName(subTag) || elem->hasLocalName(supTag))                return true;            break;        case CSSPropertyFontStyle:            // IE inserts "em" tags for execCommand("italic"), so we remove them, even though they're not strictly presentational            if (elem->hasLocalName(iTag) || elem->hasLocalName(emTag))                return true;        }    }    return false;}void ApplyStyleCommand::removeHTMLStyleNode(HTMLElement *elem){    // This node can be removed.    // EDIT FIXME: This does not handle the case where the node    // has attributes. But how often do people add attributes to <B> tags?     // Not so often I think.    ASSERT(elem);    removeNodePreservingChildren(elem);}void ApplyStyleCommand::removeHTMLFontStyle(CSSMutableStyleDeclaration *style, HTMLElement *elem){    ASSERT(style);    ASSERT(elem);    if (!elem->hasLocalName(fontTag))        return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -