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

📄 applystylecommand.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (C) 2005, 2006, 2008, 2009 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  */#include "config.h"#include "ApplyStyleCommand.h"#include "CSSComputedStyleDeclaration.h"#include "CSSParser.h"#include "CSSProperty.h"#include "CSSPropertyNames.h"#include "CSSValueKeywords.h"#include "Document.h"#include "Editor.h"#include "Frame.h"#include "HTMLElement.h"#include "HTMLInterchange.h"#include "HTMLNames.h"#include "NodeList.h"#include "Range.h"#include "RenderObject.h"#include "Text.h"#include "TextIterator.h"#include "htmlediting.h"#include "visible_units.h"#include <wtf/StdLibExtras.h>namespace WebCore {using namespace HTMLNames;class StyleChange {public:    explicit StyleChange(CSSStyleDeclaration*, const Position&);    String cssStyle() const { return m_cssStyle; }    bool applyBold() const { return m_applyBold; }    bool applyItalic() const { return m_applyItalic; }    bool applySubscript() const { return m_applySubscript; }    bool applySuperscript() const { return m_applySuperscript; }    bool applyFontColor() const { return m_applyFontColor.length() > 0; }    bool applyFontFace() const { return m_applyFontFace.length() > 0; }    bool applyFontSize() const { return m_applyFontSize.length() > 0; }    String fontColor() { return m_applyFontColor; }    String fontFace() { return m_applyFontFace; }    String fontSize() { return m_applyFontSize; }private:    void init(PassRefPtr<CSSStyleDeclaration>, const Position&);    bool checkForLegacyHTMLStyleChange(const CSSProperty*);    static bool currentlyHasStyle(const Position&, const CSSProperty*);        String m_cssStyle;    bool m_applyBold;    bool m_applyItalic;    bool m_applySubscript;    bool m_applySuperscript;    String m_applyFontColor;    String m_applyFontFace;    String m_applyFontSize;};StyleChange::StyleChange(CSSStyleDeclaration* style, const Position& position)    : m_applyBold(false)    , m_applyItalic(false)    , m_applySubscript(false)    , m_applySuperscript(false){    init(style, position);}void StyleChange::init(PassRefPtr<CSSStyleDeclaration> style, const Position& position){    Document* document = position.node() ? position.node()->document() : 0;    if (!document || !document->frame())        return;            bool useHTMLFormattingTags = !document->frame()->editor()->shouldStyleWithCSS();                RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();        String styleText("");    bool addedDirection = false;    CSSMutableStyleDeclaration::const_iterator end = mutableStyle->end();    for (CSSMutableStyleDeclaration::const_iterator it = mutableStyle->begin(); it != end; ++it) {        const CSSProperty *property = &*it;        // If position is empty or the position passed in already has the         // style, just move on.        if (position.isNotNull() && currentlyHasStyle(position, property))            continue;                // Changing the whitespace style in a tab span would collapse the tab into a space.        if (property->id() == CSSPropertyWhiteSpace && (isTabSpanTextNode(position.node()) || isTabSpanNode((position.node()))))            continue;                // If needed, figure out if this change is a legacy HTML style change.        if (useHTMLFormattingTags && checkForLegacyHTMLStyleChange(property))            continue;        if (property->id() == CSSPropertyDirection) {            if (addedDirection)                continue;            addedDirection = true;        }        // Add this property        if (property->id() == CSSPropertyWebkitTextDecorationsInEffect) {            // we have to special-case text decorations            // FIXME: Why?            CSSProperty alteredProperty(CSSPropertyTextDecoration, property->value(), property->isImportant());            styleText += alteredProperty.cssText();        } else            styleText += property->cssText();        if (!addedDirection && property->id() == CSSPropertyUnicodeBidi) {            styleText += "direction: " + style->getPropertyValue(CSSPropertyDirection) + "; ";            addedDirection = true;        }    }    // Save the result for later    m_cssStyle = styleText.stripWhiteSpace();}// This function is the mapping from CSS styles to styling tags (like font-weight: bold to <b>)bool StyleChange::checkForLegacyHTMLStyleChange(const CSSProperty* property){    if (!property || !property->value())        return false;        String valueText(property->value()->cssText());    switch (property->id()) {        case CSSPropertyFontWeight:            if (equalIgnoringCase(valueText, "bold")) {                m_applyBold = true;                return true;            }            break;        case CSSPropertyVerticalAlign:            if (equalIgnoringCase(valueText, "sub")) {                m_applySubscript = true;                return true;            }            if (equalIgnoringCase(valueText, "super")) {                m_applySuperscript = true;                return true;            }            break;        case CSSPropertyFontStyle:            if (equalIgnoringCase(valueText, "italic") || equalIgnoringCase(valueText, "oblique")) {                m_applyItalic = true;                return true;            }            break;        case CSSPropertyColor: {            RGBA32 rgba = 0;            CSSParser::parseColor(rgba, valueText);            Color color(rgba);            m_applyFontColor = color.name();            return true;        }        case CSSPropertyFontFamily:            m_applyFontFace = valueText;            return true;        case CSSPropertyFontSize:            if (property->value()->cssValueType() == CSSValue::CSS_PRIMITIVE_VALUE) {                CSSPrimitiveValue *value = static_cast<CSSPrimitiveValue *>(property->value());                if (value->primitiveType() < CSSPrimitiveValue::CSS_PX || value->primitiveType() > CSSPrimitiveValue::CSS_PC)                    // Size keyword or relative unit.                    return false;                float number = value->getFloatValue(CSSPrimitiveValue::CSS_PX);                if (number <= 9)                    m_applyFontSize = "1";                else if (number <= 10)                    m_applyFontSize = "2";                else if (number <= 13)                    m_applyFontSize = "3";                else if (number <= 16)                    m_applyFontSize = "4";                else if (number <= 18)                    m_applyFontSize = "5";                else if (number <= 24)                    m_applyFontSize = "6";                else                    m_applyFontSize = "7";                // Huge quirk in Microsft Entourage is that they understand CSS font-size, but also write                 // out legacy 1-7 values in font tags (I guess for mailers that are not CSS-savvy at all,                 // like Eudora). Yes, they write out *both*. We need to write out both as well. Return false.                return false;             }            else {                // Can't make sense of the number. Put no font size.                return true;            }    }    return false;}bool StyleChange::currentlyHasStyle(const Position &pos, const CSSProperty *property){    ASSERT(pos.isNotNull());    RefPtr<CSSComputedStyleDeclaration> style = pos.computedStyle();    RefPtr<CSSValue> value = style->getPropertyCSSValue(property->id(), DoNotUpdateLayout);    if (!value)        return false;    return equalIgnoringCase(value->cssText(), property->value()->cssText());}static String& styleSpanClassString(){    DEFINE_STATIC_LOCAL(String, styleSpanClassString, ((AppleStyleSpanClass)));    return styleSpanClassString;}bool isStyleSpan(const Node *node){    if (!node || !node->isHTMLElement())        return false;    const HTMLElement* elem = static_cast<const HTMLElement*>(node);    return elem->hasLocalName(spanAttr) && elem->getAttribute(classAttr) == styleSpanClassString();}static bool isUnstyledStyleSpan(const Node* node){    if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))        return false;    const HTMLElement* elem = static_cast<const HTMLElement*>(node);    CSSMutableStyleDeclaration* inlineStyleDecl = elem->inlineStyleDecl();    return (!inlineStyleDecl || inlineStyleDecl->length() == 0) && elem->getAttribute(classAttr) == styleSpanClassString();}static bool isSpanWithoutAttributesOrUnstyleStyleSpan(const Node* node){    if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))        return false;    const HTMLElement* elem = static_cast<const HTMLElement*>(node);    NamedAttrMap* attributes = elem->attributes(true); // readonly    if (attributes->length() == 0)        return true;    return isUnstyledStyleSpan(node);}static bool isEmptyFontTag(const Node *node){    if (!node || !node->hasTagName(fontTag))        return false;    const Element *elem = static_cast<const Element *>(node);    NamedAttrMap *map = elem->attributes(true); // true for read-only    return (!map || map->length() == 1) && elem->getAttribute(classAttr) == styleSpanClassString();}static PassRefPtr<Element> createFontElement(Document* document){    RefPtr<Element> fontNode = createHTMLElement(document, fontTag);    fontNode->setAttribute(classAttr, styleSpanClassString());    return fontNode.release();}PassRefPtr<HTMLElement> createStyleSpanElement(Document* document){    RefPtr<HTMLElement> styleElement = createHTMLElement(document, spanTag);    styleElement->setAttribute(classAttr, styleSpanClassString());    return styleElement.release();}ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, EditAction editingAction, EPropertyLevel propertyLevel)    : CompositeEditCommand(document)    , m_style(style->makeMutable())    , m_editingAction(editingAction)    , m_propertyLevel(propertyLevel)    , m_start(endingSelection().start().downstream())    , m_end(endingSelection().end().upstream())    , m_useEndingSelection(true)    , m_styledInlineElement(0)    , m_removeOnly(false){}ApplyStyleCommand::ApplyStyleCommand(Document* document, CSSStyleDeclaration* style, const Position& start, const Position& end, EditAction editingAction, EPropertyLevel propertyLevel)    : CompositeEditCommand(document)    , m_style(style->makeMutable())    , m_editingAction(editingAction)    , m_propertyLevel(propertyLevel)    , m_start(start)    , m_end(end)    , m_useEndingSelection(false)    , m_styledInlineElement(0)    , m_removeOnly(false){}ApplyStyleCommand::ApplyStyleCommand(PassRefPtr<Element> element, bool removeOnly, EditAction editingAction)    : CompositeEditCommand(element->document())

⌨️ 快捷键说明

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