document.cpp

来自「linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自Web」· C++ 代码 · 共 2,092 行 · 第 1/5 页

CPP
2,092
字号
    if (Settings* settings = this->settings())        return settings->defaultTextEncodingName();    return String();}void Document::setCharset(const String& charset){    if (!decoder())        return;    decoder()->setEncoding(charset, TextResourceDecoder::UserChosenEncoding);}void Document::setXMLVersion(const String& version, ExceptionCode& ec){    if (!implementation()->hasFeature("XML", String())) {        ec = NOT_SUPPORTED_ERR;        return;    }       // FIXME: Also raise NOT_SUPPORTED_ERR if the version is set to a value that is not supported by this Document.    m_xmlVersion = version;}void Document::setXMLStandalone(bool standalone, ExceptionCode& ec){    if (!implementation()->hasFeature("XML", String())) {        ec = NOT_SUPPORTED_ERR;        return;    }    m_xmlStandalone = standalone;}void Document::setDocumentURI(const String& uri){    m_documentURI = uri;    updateBaseURL();}KURL Document::baseURI() const{    return m_baseURL;}Element* Document::elementFromPoint(int x, int y) const{    if (!renderer())        return 0;    HitTestRequest request(HitTestRequest::ReadOnly |                           HitTestRequest::Active);    HitTestResult result(IntPoint(x, y));    renderView()->layer()->hitTest(request, result);     Node* n = result.innerNode();    while (n && !n->isElementNode())        n = n->parentNode();    if (n)        n = n->shadowAncestorNode();    return static_cast<Element*>(n);}void Document::addElementById(const AtomicString& elementId, Element* element){    typedef HashMap<AtomicStringImpl*, Element*>::iterator iterator;    if (!m_duplicateIds.contains(elementId.impl())) {        // Fast path. The ID is not already in m_duplicateIds, so we assume that it's        // also not already in m_elementsById and do an add. If that add succeeds, we're done.        pair<iterator, bool> addResult = m_elementsById.add(elementId.impl(), element);        if (addResult.second)            return;        // The add failed, so this ID was already cached in m_elementsById.        // There are multiple elements with this ID. Remove the m_elementsById        // cache for this ID so getElementById searches for it next time it is called.        m_elementsById.remove(addResult.first);        m_duplicateIds.add(elementId.impl());    } else {        // There are multiple elements with this ID. If it exists, remove the m_elementsById        // cache for this ID so getElementById searches for it next time it is called.        iterator cachedItem = m_elementsById.find(elementId.impl());        if (cachedItem != m_elementsById.end()) {            m_elementsById.remove(cachedItem);            m_duplicateIds.add(elementId.impl());        }    }    m_duplicateIds.add(elementId.impl());}void Document::removeElementById(const AtomicString& elementId, Element* element){    if (m_elementsById.get(elementId.impl()) == element)        m_elementsById.remove(elementId.impl());    else        m_duplicateIds.remove(elementId.impl());}Element* Document::getElementByAccessKey(const String& key) const{    if (key.isEmpty())        return 0;    if (!m_accessKeyMapValid) {        for (Node* n = firstChild(); n; n = n->traverseNextNode()) {            if (!n->isElementNode())                continue;            Element* element = static_cast<Element*>(n);            const AtomicString& accessKey = element->getAttribute(accesskeyAttr);            if (!accessKey.isEmpty())                m_elementsByAccessKey.set(accessKey.impl(), element);        }        m_accessKeyMapValid = true;    }    return m_elementsByAccessKey.get(key.impl());}void Document::updateTitle(){    if (Frame* f = frame())        f->loader()->setTitle(m_title);}void Document::setTitle(const String& title, Element* titleElement){    if (!titleElement) {        // Title set by JavaScript -- overrides any title elements.        m_titleSetExplicitly = true;        if (!isHTMLDocument())            m_titleElement = 0;        else if (!m_titleElement) {            if (HTMLElement* headElement = head()) {                m_titleElement = createElement(titleTag, false);                ExceptionCode ec = 0;                headElement->appendChild(m_titleElement, ec);                ASSERT(!ec);            }        }    } else if (titleElement != m_titleElement) {        if (m_titleElement || m_titleSetExplicitly)            // Only allow the first title element to change the title -- others have no effect.            return;        m_titleElement = titleElement;    }    if (m_title == title)        return;    m_title = title;    updateTitle();    if (m_titleSetExplicitly && m_titleElement && m_titleElement->hasTagName(titleTag))        static_cast<HTMLTitleElement*>(m_titleElement.get())->setText(m_title);}void Document::removeTitle(Element* titleElement){    if (m_titleElement != titleElement)        return;    m_titleElement = 0;    m_titleSetExplicitly = false;    // Update title based on first title element in the head, if one exists.    if (HTMLElement* headElement = head()) {        for (Node* e = headElement->firstChild(); e; e = e->nextSibling())            if (e->hasTagName(titleTag)) {                HTMLTitleElement* titleElement = static_cast<HTMLTitleElement*>(e);                setTitle(titleElement->text(), titleElement);                break;            }    }    if (!m_titleElement && !m_title.isEmpty()) {        m_title = "";        updateTitle();    }}String Document::nodeName() const{    return "#document";}Node::NodeType Document::nodeType() const{    return DOCUMENT_NODE;}FrameView* Document::view() const{    return m_frame ? m_frame->view() : 0;}Page* Document::page() const{    return m_frame ? m_frame->page() : 0;    }Settings* Document::settings() const{    return m_frame ? m_frame->settings() : 0;}PassRefPtr<Range> Document::createRange(){    return Range::create(this);}PassRefPtr<NodeIterator> Document::createNodeIterator(Node* root, unsigned whatToShow,     PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec){    if (!root) {        ec = NOT_SUPPORTED_ERR;        return 0;    }    return NodeIterator::create(root, whatToShow, filter, expandEntityReferences);}PassRefPtr<TreeWalker> Document::createTreeWalker(Node *root, unsigned whatToShow,     PassRefPtr<NodeFilter> filter, bool expandEntityReferences, ExceptionCode& ec){    if (!root) {        ec = NOT_SUPPORTED_ERR;        return 0;    }    return TreeWalker::create(root, whatToShow, filter, expandEntityReferences);}void Document::setDocumentChanged(bool b){    if (b) {        if (!m_docChanged) {            if (!changedDocuments)                changedDocuments = new HashSet<Document*>;            changedDocuments->add(this);        }        if (m_accessKeyMapValid) {            m_accessKeyMapValid = false;            m_elementsByAccessKey.clear();        }    } else {        if (m_docChanged && changedDocuments)            changedDocuments->remove(this);    }    m_docChanged = b;}void Document::recalcStyle(StyleChange change){    // we should not enter style recalc while painting    if (view() && view()->isPainting()) {        ASSERT(!view()->isPainting());        return;    }        if (m_inStyleRecalc)        return; // Guard against re-entrancy. -dwh    m_inStyleRecalc = true;    suspendPostAttachCallbacks();    if (view())        view()->pauseScheduledEvents();        ASSERT(!renderer() || renderArena());    if (!renderer() || !renderArena())        goto bail_out;    if (change == Force) {        // style selector may set this again during recalc        m_hasNodesWithPlaceholderStyle = false;                RefPtr<RenderStyle> documentStyle = RenderStyle::create();        documentStyle->setDisplay(BLOCK);        documentStyle->setVisuallyOrdered(visuallyOrdered);        documentStyle->setZoom(frame()->pageZoomFactor());        m_styleSelector->setStyle(documentStyle);            FontDescription fontDescription;        fontDescription.setUsePrinterFont(printing());        if (Settings* settings = this->settings()) {            fontDescription.setRenderingMode(settings->fontRenderingMode());            if (printing() && !settings->shouldPrintBackgrounds())                documentStyle->setForceBackgroundsToWhite(true);            const AtomicString& stdfont = settings->standardFontFamily();            if (!stdfont.isEmpty()) {                fontDescription.firstFamily().setFamily(stdfont);                fontDescription.firstFamily().appendFamily(0);            }            fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);            m_styleSelector->setFontSize(fontDescription, m_styleSelector->fontSizeForKeyword(CSSValueMedium, inCompatMode(), false));        }        documentStyle->setFontDescription(fontDescription);        documentStyle->font().update(m_styleSelector->fontSelector());        if (inCompatMode())            documentStyle->setHtmlHacks(true); // enable html specific rendering tricks        StyleChange ch = diff(documentStyle.get(), renderer()->style());        if (renderer() && ch != NoChange)            renderer()->setStyle(documentStyle.release());        if (change != Force)            change = ch;    }    for (Node* n = firstChild(); n; n = n->nextSibling())        if (change >= Inherit || n->hasChangedChild() || n->changed())            n->recalcStyle(change);    if (view()) {        if (changed())            view()->layout();#if USE(ACCELERATED_COMPOSITING)        else {            // If we didn't update compositing layers because of layout(), we need to do so here.            view()->updateCompositingLayers();        }#endif    }bail_out:    setChanged(NoStyleChange);    setHasChangedChild(false);    setDocumentChanged(false);    if (view())        view()->resumeScheduledEvents();    resumePostAttachCallbacks();    m_inStyleRecalc = false;    // If we wanted to call implicitClose() during recalcStyle, do so now that we're finished.    if (m_closeAfterStyleRecalc) {        m_closeAfterStyleRecalc = false;        implicitClose();    }}void Document::updateRendering(){    if (!hasChangedChild() || inPageCache())        return;            if (m_frame)        m_frame->animation()->beginAnimationUpdate();            recalcStyle(NoChange);        // Tell the animation controller that updateRendering is finished and it can do any post-processing    if (m_frame)        m_frame->animation()->endAnimationUpdate();}void Document::updateDocumentsRendering(){    if (!changedDocuments)        return;    while (changedDocuments->size()) {        HashSet<Document*>::iterator it = changedDocuments->begin();        Document* doc = *it;        changedDocuments->remove(it);                doc->m_docChanged = false;        doc->updateRendering();    }}void Document::updateLayout(){    if (Element* oe = ownerElement())        oe->document()->updateLayout();    updateRendering();    // Only do a layout if changes have occurred that make it necessary.          FrameView* v = view();    if (v && renderer() && (v->layoutPending() || renderer()->needsLayout()))        v->layout();}// FIXME: This is a bad idea and needs to be removed eventually.// Other browsers load stylesheets before they continue parsing the web page.// Since we don't, we can run JavaScript code that needs answers before the// stylesheets are loaded. Doing a layout ignoring the pending stylesheets// lets us get reasonable answers. The long term solution to this problem is// to instead suspend JavaScript execution.void Document::updateLayoutIgnorePendingStylesheets(){    bool oldIgnore = m_ignorePendingStylesheets;        if (!haveStylesheetsLoaded()) {        m_ignorePendingStylesheets = true;        // FIXME: We are willing to attempt to suppress painting with outdated style info only once.  Our assumption is that it would be        // dangerous to try to stop it a second time, after page content has already been loaded and displayed        // with accurate style information.  (Our suppression involves blanking the whole page at the        // moment.  If it were more refined, we might be able to do something better.)        // It's worth noting though that this entire method is a hack, since what we really want to do is        // suspend JS instead of doing a layout with inaccurate information.        if (body() && !body()->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) {            m_pendingSheetLayout = DidLayoutWithPendingSheets;            updateStyleSelector();        } else if (m_hasNodesWithPlaceholderStyle)            // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes             // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive             // but here we need up-to-date style immediatly.            recalcStyle(Force);    }    updateLayout();    m_ignorePendingStylesheets = oldIgnore;}void Document::attach(){    ASSERT(!attached());    ASSERT(!m_inPageCache);    ASSERT(!m_axObjectCache);    if (!m_renderArena)

⌨️ 快捷键说明

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