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

📄 applystylecommand.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    , m_style(CSSMutableStyleDeclaration::create())    , m_editingAction(editingAction)    , m_propertyLevel(PropertyDefault)    , m_start(endingSelection().start().downstream())    , m_end(endingSelection().end().upstream())    , m_useEndingSelection(true)    , m_styledInlineElement(element)    , m_removeOnly(removeOnly){}void ApplyStyleCommand::updateStartEnd(const Position& newStart, const Position& newEnd){    ASSERT(Range::compareBoundaryPoints(newEnd, newStart) >= 0);    if (!m_useEndingSelection && (newStart != m_start || newEnd != m_end))        m_useEndingSelection = true;    setEndingSelection(VisibleSelection(newStart, newEnd, VP_DEFAULT_AFFINITY));    m_start = newStart;    m_end = newEnd;}Position ApplyStyleCommand::startPosition(){    if (m_useEndingSelection)        return endingSelection().start();        return m_start;}Position ApplyStyleCommand::endPosition(){    if (m_useEndingSelection)        return endingSelection().end();        return m_end;}void ApplyStyleCommand::doApply(){    switch (m_propertyLevel) {        case PropertyDefault: {            // apply the block-centric properties of the style            RefPtr<CSSMutableStyleDeclaration> blockStyle = m_style->copyBlockProperties();            if (blockStyle->length())                applyBlockStyle(blockStyle.get());            // apply any remaining styles to the inline elements            // NOTE: hopefully, this string comparison is the same as checking for a non-null diff            if (blockStyle->length() < m_style->length() || m_styledInlineElement) {                RefPtr<CSSMutableStyleDeclaration> inlineStyle = m_style->copy();                applyRelativeFontStyleChange(inlineStyle.get());                blockStyle->diff(inlineStyle.get());                applyInlineStyle(inlineStyle.get());            }            break;        }        case ForceBlockProperties:            // Force all properties to be applied as block styles.            applyBlockStyle(m_style.get());            break;    }}EditAction ApplyStyleCommand::editingAction() const{    return m_editingAction;}void ApplyStyleCommand::applyBlockStyle(CSSMutableStyleDeclaration *style){    // 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();    // get 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;    }            VisiblePosition visibleStart(start);    VisiblePosition visibleEnd(end);    // Save and restore the selection endpoints using their indices in the document, since    // addBlockStyleIfNeeded may moveParagraphs, which can remove these endpoints.    // Calculate start and end indices from the start of the tree that they're in.    Node* scope = highestAncestor(visibleStart.deepEquivalent().node());    Position rangeStart(scope, 0);    RefPtr<Range> startRange = Range::create(document(), rangeStart, rangeCompliantEquivalent(visibleStart.deepEquivalent()));    RefPtr<Range> endRange = Range::create(document(), rangeStart, rangeCompliantEquivalent(visibleEnd.deepEquivalent()));    int startIndex = TextIterator::rangeLength(startRange.get(), true);    int endIndex = TextIterator::rangeLength(endRange.get(), true);        VisiblePosition paragraphStart(startOfParagraph(visibleStart));    VisiblePosition nextParagraphStart(endOfParagraph(paragraphStart).next());    VisiblePosition beyondEnd(endOfParagraph(visibleEnd).next());    while (paragraphStart.isNotNull() && paragraphStart != beyondEnd) {        StyleChange styleChange(style, paragraphStart.deepEquivalent());        if (styleChange.cssStyle().length() > 0 || m_removeOnly) {            RefPtr<Node> block = enclosingBlock(paragraphStart.deepEquivalent().node());            RefPtr<Node> newBlock = moveParagraphContentsToNewBlockIfNecessary(paragraphStart.deepEquivalent());            if (newBlock)                block = newBlock;            ASSERT(block->isHTMLElement());            if (block->isHTMLElement()) {                removeCSSStyle(style, static_cast<HTMLElement*>(block.get()));                if (!m_removeOnly)                    addBlockStyle(styleChange, static_cast<HTMLElement*>(block.get()));            }        }        paragraphStart = nextParagraphStart;        nextParagraphStart = endOfParagraph(paragraphStart).next();    }        startRange = TextIterator::rangeFromLocationAndLength(static_cast<Element*>(scope), startIndex, 0, true);    endRange = TextIterator::rangeFromLocationAndLength(static_cast<Element*>(scope), endIndex, 0, true);    if (startRange && endRange)        updateStartEnd(startRange->startPosition(), endRange->startPosition());}#define NoFontDelta (0.0f)#define MinimumFontSize (0.1f)void ApplyStyleCommand::applyRelativeFontStyleChange(CSSMutableStyleDeclaration *style){    RefPtr<CSSValue> value = style->getPropertyCSSValue(CSSPropertyFontSize);    if (value) {        // Explicit font size overrides any delta.        style->removeProperty(CSSPropertyWebkitFontSizeDelta);        return;    }    // Get the adjustment amount out of the style.    value = style->getPropertyCSSValue(CSSPropertyWebkitFontSizeDelta);    if (!value)        return;    float adjustment = NoFontDelta;    if (value->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {        CSSPrimitiveValue *primitiveValue = static_cast<CSSPrimitiveValue *>(value.get());        if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_PX) {            // Only PX handled now. If we handle more types in the future, perhaps            // a switch statement here would be more appropriate.            adjustment = primitiveValue->getFloatValue();        }    }    style->removeProperty(CSSPropertyWebkitFontSizeDelta);    if (adjustment == NoFontDelta)        return;        Position start = startPosition();    Position end = endPosition();    if (Range::compareBoundaryPoints(end, start) < 0) {        Position swap = start;        start = end;        end = swap;    }        // Join up any adjacent text nodes.    if (start.node()->isTextNode()) {        joinChildTextNodes(start.node()->parentNode(), start, end);        start = startPosition();        end = endPosition();    }    if (end.node()->isTextNode() && start.node()->parentNode() != end.node()->parentNode()) {        joinChildTextNodes(end.node()->parentNode(), start, end);        start = startPosition();        end = endPosition();    }    // Split the start text nodes if needed to apply style.    bool splitStart = splitTextAtStartIfNeeded(start, end);     if (splitStart) {        start = startPosition();        end = endPosition();    }    bool splitEnd = splitTextAtEndIfNeeded(start, end);    if (splitEnd) {        start = startPosition();        end = endPosition();    }    // Calculate loop end point.    // If the end node is before the start node (can only happen if the end node is    // an ancestor of the start node), we gather nodes up to the next sibling of the end node    Node *beyondEnd;    if (start.node()->isDescendantOf(end.node()))        beyondEnd = end.node()->traverseNextSibling();    else        beyondEnd = end.node()->traverseNextNode();        start = start.upstream(); // Move upstream to ensure we do not add redundant spans.    Node *startNode = start.node();    if (startNode->isTextNode() && start.offset() >= caretMaxOffset(startNode)) // Move out of text node if range does not include its characters.        startNode = startNode->traverseNextNode();    // Store away font size before making any changes to the document.    // This ensures that changes to one node won't effect another.    HashMap<Node*, float> startingFontSizes;    for (Node *node = startNode; node != beyondEnd; node = node->traverseNextNode())        startingFontSizes.set(node, computedFontSize(node));    // These spans were added by us. If empty after font size changes, they can be removed.    Vector<RefPtr<HTMLElement> > unstyledSpans;        Node* lastStyledNode = 0;    for (Node* node = startNode; node != beyondEnd; node = node->traverseNextNode()) {        RefPtr<HTMLElement> element;        if (node->isHTMLElement()) {            // Only work on fully selected nodes.            if (!nodeFullySelected(node, start, end))                continue;            element = static_cast<HTMLElement*>(node);        } else if (node->isTextNode() && node->renderer() && node->parentNode() != lastStyledNode) {            // Last styled node was not parent node of this text node, but we wish to style this            // text node. To make this possible, add a style span to surround this text node.            RefPtr<HTMLElement> span = createStyleSpanElement(document());            surroundNodeRangeWithElement(node, node, span.get());            element = span.release();        }  else {            // Only handle HTML elements and text nodes.            continue;        }        lastStyledNode = node;        CSSMutableStyleDeclaration* inlineStyleDecl = element->getInlineStyleDecl();        float currentFontSize = computedFontSize(node);        float desiredFontSize = max(MinimumFontSize, startingFontSizes.get(node) + adjustment);        RefPtr<CSSValue> value = inlineStyleDecl->getPropertyCSSValue(CSSPropertyFontSize);        if (value) {            inlineStyleDecl->removeProperty(CSSPropertyFontSize, true);            currentFontSize = computedFontSize(node);        }        if (currentFontSize != desiredFontSize) {            inlineStyleDecl->setProperty(CSSPropertyFontSize, String::number(desiredFontSize) + "px", false, false);            setNodeAttribute(element.get(), styleAttr, inlineStyleDecl->cssText());        }        if (inlineStyleDecl->length() == 0) {            removeNodeAttribute(element.get(), styleAttr);            // FIXME: should this be isSpanWithoutAttributesOrUnstyleStyleSpan?  Need a test.            if (isUnstyledStyleSpan(element.get()))                unstyledSpans.append(element.release());        }    }    size_t size = unstyledSpans.size();    for (size_t i = 0; i < size; ++i)        removeNodePreservingChildren(unstyledSpans[i].get());}#undef NoFontDelta#undef MinimumFontSizestatic Node* dummySpanAncestorForNode(const Node* node){    while (node && !isStyleSpan(node))        node = node->parent();        return node ? node->parent() : 0;}void ApplyStyleCommand::cleanupUnstyledAppleStyleSpans(Node* dummySpanAncestor){    if (!dummySpanAncestor)        return;    // Dummy spans are created when text node is split, so that style information    // can be propagated, which can result in more splitting. If a dummy span gets    // cloned/split, the new node is always a sibling of it. Therefore, we scan    // all the children of the dummy's parent    Node* next;    for (Node* node = dummySpanAncestor->firstChild(); node; node = next) {        next = node->nextSibling();        if (isUnstyledStyleSpan(node))            removeNodePreservingChildren(node);        node = next;    }}HTMLElement* ApplyStyleCommand::splitAncestorsWithUnicodeBidi(Node* node, bool before, RefPtr<CSSPrimitiveValue> allowedDirection){    // We are allowed to leave the highest ancestor with unicode-bidi unsplit if it is unicode-bidi: embed and direction: allowedDirection.    // In that case, we return the unsplit ancestor. Otherwise, we return 0.    Node* block = enclosingBlock(node);    if (!block)        return 0;    Node* highestAncestorWithUnicodeBidi = 0;    Node* nextHighestAncestorWithUnicodeBidi = 0;    RefPtr<CSSPrimitiveValue> highestAncestorUnicodeBidi;    for (Node* n = node->parent(); n != block; n = n->parent()) {        RefPtr<CSSValue> unicodeBidi = computedStyle(n)->getPropertyCSSValue(CSSPropertyUnicodeBidi);        if (unicodeBidi) {            ASSERT(unicodeBidi->isPrimitiveValue());            if (static_cast<CSSPrimitiveValue*>(unicodeBidi.get())->getIdent() != CSSValueNormal) {                highestAncestorUnicodeBidi = static_cast<CSSPrimitiveValue*>(unicodeBidi.get());                nextHighestAncestorWithUnicodeBidi = highestAncestorWithUnicodeBidi;                highestAncestorWithUnicodeBidi = n;            }        }    }    if (!highestAncestorWithUnicodeBidi)        return 0;    HTMLElement* unsplitAncestor = 0;    if (allowedDirection && highestAncestorUnicodeBidi->getIdent() != CSSValueBidiOverride) {        RefPtr<CSSValue> highestAncestorDirection = computedStyle(highestAncestorWithUnicodeBidi)->getPropertyCSSValue(CSSPropertyDirection);        ASSERT(highestAncestorDirection->isPrimitiveValue());        if (static_cast<CSSPrimitiveValue*>(highestAncestorDirection.get())->getIdent() == allowedDirection->getIdent() && highestAncestorWithUnicodeBidi->isHTMLElement()) {            if (!nextHighestAncestorWithUnicodeBidi)                return static_cast<HTMLElement*>(highestAncestorWithUnicodeBidi);            unsplitAncestor = static_cast<HTMLElement*>(highestAncestorWithUnicodeBidi);            highestAncestorWithUnicodeBidi = nextHighestAncestorWithUnicodeBidi;        }    }    // Split every ancestor through highest ancestor with embedding.    Node* n = node;    while (true) {        Element* parent = static_cast<Element*>(n->parent());

⌨️ 快捷键说明

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