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

📄 rendertextcontrol.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/** * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)   * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB.  If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * */#include "config.h"#include "RenderTextControl.h"#include "CharacterNames.h"#include "Editor.h"#include "Event.h"#include "EventNames.h"#include "Frame.h"#include "HTMLBRElement.h"#include "HTMLFormControlElement.h"#include "HTMLNames.h"#include "HitTestResult.h"#include "RenderLayer.h"#include "RenderText.h"#include "ScrollbarTheme.h"#include "SelectionController.h"#include "Text.h"#include "TextControlInnerElements.h"#include "TextIterator.h"using namespace std;namespace WebCore {using namespace HTMLNames;// Value chosen by observation.  This can be tweaked.static const int minColorContrastValue = 1300;static Color disabledTextColor(const Color& textColor, const Color& backgroundColor){    // The explicit check for black is an optimization for the 99% case (black on white).    // This also means that black on black will turn into grey on black when disabled.    Color disabledColor;    if (textColor.rgb() == Color::black || differenceSquared(textColor, Color::white) > differenceSquared(backgroundColor, Color::white))        disabledColor = textColor.light();    else        disabledColor = textColor.dark();        // If there's not very much contrast between the disabled color and the background color,    // just leave the text color alone.  We don't want to change a good contrast color scheme so that it has really bad contrast.    // If the the contrast was already poor, then it doesn't do any good to change it to a different poor contrast color scheme.    if (differenceSquared(disabledColor, backgroundColor) < minColorContrastValue)        return textColor;        return disabledColor;}RenderTextControl::RenderTextControl(Node* node)    : RenderBlock(node)    , m_edited(false)    , m_userEdited(false){}RenderTextControl::~RenderTextControl(){    // The children renderers have already been destroyed by destroyLeftoverChildren    if (m_innerText)        m_innerText->detach();}void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle){    RenderBlock::styleDidChange(diff, oldStyle);    if (m_innerText) {        RenderBlock* textBlockRenderer = toRenderBlock(m_innerText->renderer());        RefPtr<RenderStyle> textBlockStyle = createInnerTextStyle(style());        // We may have set the width and the height in the old style in layout().        // Reset them now to avoid getting a spurious layout hint.        textBlockRenderer->style()->setHeight(Length());        textBlockRenderer->style()->setWidth(Length());        textBlockRenderer->setStyle(textBlockStyle);        for (Node* n = m_innerText->firstChild(); n; n = n->traverseNextNode(m_innerText.get())) {            if (n->renderer())                n->renderer()->setStyle(textBlockStyle);        }    }    setHasOverflowClip(false);    setReplaced(isInline());}static inline bool updateUserModifyProperty(Node* node, RenderStyle* style){    bool isEnabled = true;    bool isReadOnlyControl = false;    if (node->isElementNode()) {        FormControlElement* formControlElement = toFormControlElement(static_cast<Element*>(node));        ASSERT(formControlElement);        isEnabled = formControlElement->isEnabled();        isReadOnlyControl = formControlElement->isReadOnlyControl();    }    style->setUserModify((isReadOnlyControl || !isEnabled) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);    return !isEnabled;}void RenderTextControl::adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const{    // The inner block, if present, always has its direction set to LTR,    // so we need to inherit the direction from the element.    textBlockStyle->setDirection(style()->direction());    bool disabled = updateUserModifyProperty(node(), textBlockStyle);    if (disabled)        textBlockStyle->setColor(disabledTextColor(textBlockStyle->color(), startStyle->backgroundColor()));}void RenderTextControl::createSubtreeIfNeeded(TextControlInnerElement* innerBlock){    if (!m_innerText) {        // Create the text block element        // For non-search fields, there is no intermediate innerBlock as the shadow node.        // m_innerText will be the shadow node in that case.                RenderStyle* parentStyle = innerBlock ? innerBlock->renderer()->style() : style();        m_innerText = new TextControlInnerTextElement(document(), innerBlock ? 0 : node());        m_innerText->attachInnerElement(innerBlock ? innerBlock : node(), createInnerTextStyle(parentStyle), renderArena());    }}int RenderTextControl::textBlockHeight() const{    return height() - paddingTop() - paddingBottom() - borderTop() - borderBottom();}int RenderTextControl::textBlockWidth() const{    return width() - paddingLeft() - paddingRight() - borderLeft() - borderRight()           - m_innerText->renderBox()->paddingLeft() - m_innerText->renderBox()->paddingRight();}void RenderTextControl::updateFromElement(){    updateUserModifyProperty(node(), m_innerText->renderer()->style());}void RenderTextControl::setInnerTextValue(const String& innerTextValue){    String value;    if (innerTextValue.isNull())        value = "";    else {        value = innerTextValue;         value = document()->displayStringModifiedByEncoding(value);    }    if (value != text() || !m_innerText->hasChildNodes()) {        if (value != text()) {            if (Frame* frame = document()->frame())                frame->editor()->clearUndoRedoOperations();        }        ExceptionCode ec = 0;        m_innerText->setInnerText(value, ec);        ASSERT(!ec);        if (value.endsWith("\n") || value.endsWith("\r")) {            m_innerText->appendChild(new HTMLBRElement(brTag, document()), ec);            ASSERT(!ec);        }        m_edited = false;        m_userEdited = false;    }    formControlElement()->setValueMatchesRenderer();}void RenderTextControl::setUserEdited(bool isUserEdited){    m_userEdited = isUserEdited;    document()->setIgnoreAutofocus(isUserEdited);}int RenderTextControl::selectionStart(){    Frame* frame = document()->frame();    if (!frame)        return 0;    return indexForVisiblePosition(frame->selection()->start());}int RenderTextControl::selectionEnd(){    Frame* frame = document()->frame();    if (!frame)        return 0;    return indexForVisiblePosition(frame->selection()->end());}void RenderTextControl::setSelectionStart(int start){    setSelectionRange(start, max(start, selectionEnd()));}void RenderTextControl::setSelectionEnd(int end){    setSelectionRange(min(end, selectionStart()), end);}void RenderTextControl::select(){    setSelectionRange(0, text().length());}void RenderTextControl::setSelectionRange(int start, int end){    end = max(end, 0);    start = min(max(start, 0), end);    document()->updateLayout();    if (style()->visibility() == HIDDEN || !m_innerText || !m_innerText->renderer() || !m_innerText->renderBox()->height()) {        cacheSelection(start, end);        return;    }    VisiblePosition startPosition = visiblePositionForIndex(start);    VisiblePosition endPosition;    if (start == end)        endPosition = startPosition;    else        endPosition = visiblePositionForIndex(end);    ASSERT(startPosition.isNotNull() && endPosition.isNotNull());    ASSERT(startPosition.deepEquivalent().node()->shadowAncestorNode() == node() && endPosition.deepEquivalent().node()->shadowAncestorNode() == node());    VisibleSelection newSelection = VisibleSelection(startPosition, endPosition);    if (Frame* frame = document()->frame())        frame->selection()->setSelection(newSelection);    // FIXME: Granularity is stored separately on the frame, but also in the selection controller.    // The granularity in the selection controller should be used, and then this line of code would not be needed.    if (Frame* frame = document()->frame())        frame->setSelectionGranularity(CharacterGranularity);}VisibleSelection RenderTextControl::selection(int start, int end) const{    return VisibleSelection(VisiblePosition(m_innerText.get(), start, VP_DEFAULT_AFFINITY),                     VisiblePosition(m_innerText.get(), end, VP_DEFAULT_AFFINITY));}VisiblePosition RenderTextControl::visiblePositionForIndex(int index){    if (index <= 0)        return VisiblePosition(m_innerText.get(), 0, DOWNSTREAM);    ExceptionCode ec = 0;    RefPtr<Range> range = Range::create(document());    range->selectNodeContents(m_innerText.get(), ec);    ASSERT(!ec);    CharacterIterator it(range.get());    it.advance(index - 1);    Node* endContainer = it.range()->endContainer(ec);    ASSERT(!ec);    int endOffset = it.range()->endOffset(ec);    ASSERT(!ec);    return VisiblePosition(endContainer, endOffset, UPSTREAM);}int RenderTextControl::indexForVisiblePosition(const VisiblePosition& pos){    Position indexPosition = pos.deepEquivalent();    if (!indexPosition.node() || indexPosition.node()->rootEditableElement() != m_innerText)        return 0;    ExceptionCode ec = 0;    RefPtr<Range> range = Range::create(document());    range->setStart(m_innerText.get(), 0, ec);    ASSERT(!ec);    range->setEnd(indexPosition.node(), indexPosition.offset(), ec);    ASSERT(!ec);

⌨️ 快捷键说明

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