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 + -
显示快捷键?