root/trunk/WebCore/html/HTMLDocument.cpp

Revision 49798, 13.0 KB (checked in by eric@webkit.org, 3 weeks ago)

2009-10-19 Jens Alfke < jens@mooseyard.com>

Reviewed by Darin Adler.

Optimize string upper/lowercasing
 https://bugs.webkit.org/show_bug.cgi?id=30261

  • Added AtomicString::upper() and lower()
  • Further optimized StringImpl::lower()
  • Removed StringImpl::isLower()
  • Added QualifiedName::localNameUpper(), which is cached, thereby saving thousands of upper() calls and string allocations.
  • dom/Element.cpp: (WebCore::Element::setAttribute): Call AtomicString::lower()
  • dom/QualifiedName.cpp: (WebCore::QualifiedName::localNameUpper): New method
  • dom/QualifiedName.h: Added localNameUpper() method
  • dom/StyledElement.cpp: (WebCore::StyledElement::parseMappedAttribute): Call AtomicString::lower()
  • html/HTMLDocument.cpp: (WebCore::HTMLDocument::createElement): Call AtomicString::lower()
  • html/HTMLElement.cpp: (WebCore::HTMLElement::nodeName): Call localNameUpper()
  • platform/text/AtomicString.cpp: (WebCore::AtomicString::lower): New method (WebCore::AtomicString::upper): New method
  • platform/text/AtomicString.h: Added lower() and upper()
  • platform/text/StringImpl.cpp: Removed isLower() (WebCore::StringImpl::lower): Further optimization of initial loop
  • platform/text/StringImpl.h: Removed isLower()
  • Property svn:eol-style set to native
Line 
1/*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB.  If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 * Portions are Copyright (C) 2002 Netscape Communications Corporation.
22 * Other contributors: David Baron <dbaron@fas.harvard.edu>
23 *
24 * This library is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU Lesser General Public
26 * License as published by the Free Software Foundation; either
27 * version 2.1 of the License, or (at your option) any later version.
28 *
29 * This library is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
32 * Lesser General Public License for more details.
33 *
34 * You should have received a copy of the GNU Lesser General Public
35 * License along with this library; if not, write to the Free Software
36 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
37 *
38 * Alternatively, the document type parsing portions of this file may be used
39 * under the terms of either the Mozilla Public License Version 1.1, found at
40 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
41 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
42 * (the "GPL"), in which case the provisions of the MPL or the GPL are
43 * applicable instead of those above.  If you wish to allow use of your
44 * version of this file only under the terms of one of those two
45 * licenses (the MPL or the GPL) and not to allow others to use your
46 * version of this file under the LGPL, indicate your decision by
47 * deleting the provisions above and replace them with the notice and
48 * other provisions required by the MPL or the GPL, as the case may be.
49 * If you do not delete the provisions above, a recipient may use your
50 * version of this file under any of the LGPL, the MPL or the GPL.
51 */
52
53#include "config.h"
54#include "HTMLDocument.h"
55
56#include "CSSPropertyNames.h"
57#include "CSSStyleSelector.h"
58#include "CString.h"
59#include "CookieJar.h"
60#include "DocumentLoader.h"
61#include "DocumentType.h"
62#include "ExceptionCode.h"
63#include "FocusController.h"
64#include "Frame.h"
65#include "FrameLoader.h"
66#include "FrameTree.h"
67#include "FrameView.h"
68#include "HTMLBodyElement.h"
69#include "HTMLElementFactory.h"
70#include "HTMLNames.h"
71#include "HTMLTokenizer.h"
72#include "InspectorController.h"
73#include "KURL.h"
74#include "Page.h"
75
76#include "DocTypeStrings.cpp"
77
78namespace WebCore {
79
80using namespace HTMLNames;
81
82HTMLDocument::HTMLDocument(Frame* frame)
83    : Document(frame, false)
84{
85    clearXMLVersion();
86    setParseMode(Compat);
87}
88
89HTMLDocument::~HTMLDocument()
90{
91}
92
93int HTMLDocument::width()
94{
95    updateLayoutIgnorePendingStylesheets();
96    FrameView* frameView = view();
97    return frameView ? frameView->contentsWidth() : 0;
98}
99
100int HTMLDocument::height()
101{
102    updateLayoutIgnorePendingStylesheets();
103    FrameView* frameView = view();
104    return frameView ? frameView->contentsHeight() : 0;
105}
106
107String HTMLDocument::dir()
108{
109    HTMLElement* b = body();
110    if (!b)
111        return String();
112    return b->getAttribute(dirAttr);
113}
114
115void HTMLDocument::setDir(const String& value)
116{
117    HTMLElement* b = body();
118    if (b)
119        b->setAttribute(dirAttr, value);
120}
121
122String HTMLDocument::designMode() const
123{
124    return inDesignMode() ? "on" : "off";
125}
126
127void HTMLDocument::setDesignMode(const String& value)
128{
129    InheritedBool mode;
130    if (equalIgnoringCase(value, "on"))
131        mode = on;
132    else if (equalIgnoringCase(value, "off"))
133        mode = off;
134    else
135        mode = inherit;
136    Document::setDesignMode(mode);
137}
138
139String HTMLDocument::compatMode() const
140{
141    return inCompatMode() ? "BackCompat" : "CSS1Compat";
142}
143
144Element* HTMLDocument::activeElement()
145{
146    if (Node* node = focusedNode())
147        if (node->isElementNode())
148            return static_cast<Element*>(node);
149    return body();
150}
151
152bool HTMLDocument::hasFocus()
153{
154    Page* page = this->page();
155    if (!page)
156        return false;
157    if (!page->focusController()->isActive())
158        return false;
159    if (Frame* focusedFrame = page->focusController()->focusedFrame()) {
160        if (focusedFrame->tree()->isDescendantOf(frame()))
161            return true;
162    }
163    return false;
164}
165
166String HTMLDocument::bgColor()
167{
168    HTMLElement* b = body();
169    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
170
171    if (!bodyElement)
172        return String();
173    return bodyElement->bgColor();
174}
175
176void HTMLDocument::setBgColor(const String& value)
177{
178    HTMLElement* b = body();
179    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
180
181    if (bodyElement)
182        bodyElement->setBgColor(value);
183}
184
185String HTMLDocument::fgColor()
186{
187    HTMLElement* b = body();
188    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
189
190    if (!bodyElement)
191        return String();
192    return bodyElement->text();
193}
194
195void HTMLDocument::setFgColor(const String& value)
196{
197    HTMLElement* b = body();
198    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
199
200    if (bodyElement)
201        bodyElement->setText(value);
202}
203
204String HTMLDocument::alinkColor()
205{
206    HTMLElement* b = body();
207    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
208
209    if (!bodyElement)
210        return String();
211    return bodyElement->aLink();
212}
213
214void HTMLDocument::setAlinkColor(const String& value)
215{
216    HTMLElement* b = body();
217    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
218
219    if (bodyElement) {
220        // This check is a bit silly, but some benchmarks like to set the
221        // document's link colors over and over to the same value and we
222        // don't want to incur a style update each time.
223        if (bodyElement->aLink() != value)
224            bodyElement->setALink(value);
225    }
226}
227
228String HTMLDocument::linkColor()
229{
230    HTMLElement* b = body();
231    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
232
233    if (!bodyElement)
234        return String();
235    return bodyElement->link();
236}
237
238void HTMLDocument::setLinkColor(const String& value)
239{
240    HTMLElement* b = body();
241    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
242
243    if (bodyElement) {
244        // This check is a bit silly, but some benchmarks like to set the
245        // document's link colors over and over to the same value and we
246        // don't want to incur a style update each time.
247        if (bodyElement->link() != value)
248            bodyElement->setLink(value);
249    }
250}
251
252String HTMLDocument::vlinkColor()
253{
254    HTMLElement* b = body();
255    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
256
257    if (!bodyElement)
258        return String();
259    return bodyElement->vLink();
260}
261
262void HTMLDocument::setVlinkColor(const String& value)
263{
264    HTMLElement* b = body();
265    HTMLBodyElement* bodyElement = (b && b->hasTagName(bodyTag)) ? static_cast<HTMLBodyElement*>(b) : 0;
266
267    if (bodyElement) {
268        // This check is a bit silly, but some benchmarks like to set the
269        // document's link colors over and over to the same value and we
270        // don't want to incur a style update each time.
271        if (bodyElement->vLink() != value)
272            bodyElement->setVLink(value);
273    }
274}
275
276void HTMLDocument::captureEvents()
277{
278}
279
280void HTMLDocument::releaseEvents()
281{
282}
283
284Tokenizer *HTMLDocument::createTokenizer()
285{
286    bool reportErrors = false;
287#if ENABLE(INSPECTOR)
288    if (Page* page = this->page())
289        reportErrors = page->inspectorController()->windowVisible();
290#endif
291
292    return new HTMLTokenizer(this, reportErrors);
293}
294
295// --------------------------------------------------------------------------
296// not part of the DOM
297// --------------------------------------------------------------------------
298
299bool HTMLDocument::childAllowed(Node *newChild)
300{
301    return newChild->hasTagName(htmlTag) || newChild->isCommentNode() || (newChild->nodeType() == DOCUMENT_TYPE_NODE && !doctype());
302}
303
304PassRefPtr<Element> HTMLDocument::createElement(const AtomicString& name, ExceptionCode& ec)
305{
306    if (!isValidName(name)) {
307        ec = INVALID_CHARACTER_ERR;
308        return 0;
309    }
310    return HTMLElementFactory::createHTMLElement(QualifiedName(nullAtom, name.lower(), xhtmlNamespaceURI), this, 0, false);
311}
312
313static void addItemToMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)
314{
315    if (name.isEmpty())
316        return;
317    map.add(name.impl());
318}
319
320static void removeItemFromMap(HashCountedSet<AtomicStringImpl*>& map, const AtomicString& name)
321{
322    if (name.isEmpty())
323        return;
324    map.remove(name.impl());
325}
326
327void HTMLDocument::addNamedItem(const AtomicString& name)
328{
329    addItemToMap(m_namedItemCounts, name);
330}
331
332void HTMLDocument::removeNamedItem(const AtomicString& name)
333{ 
334    removeItemFromMap(m_namedItemCounts, name);
335}
336
337void HTMLDocument::addExtraNamedItem(const AtomicString& name)
338{
339    addItemToMap(m_extraNamedItemCounts, name);
340}
341
342void HTMLDocument::removeExtraNamedItem(const AtomicString& name)
343{ 
344    removeItemFromMap(m_extraNamedItemCounts, name);
345}
346
347void HTMLDocument::determineParseMode()
348{
349    // FIXME: It's terrible that this code runs separately and isn't just built in to the
350    // HTML tokenizer/parser.
351
352    // This code more or less mimics Mozilla's implementation (specifically the
353    // doctype parsing implemented by David Baron in Mozilla's nsParser.cpp).
354    //
355    // There are three possible parse modes:
356    // COMPAT - quirks mode emulates WinIE and NS4.  CSS parsing is also relaxed in this mode, e.g., unit types can
357    // be omitted from numbers.
358    // ALMOST STRICT - This mode is identical to strict mode except for its treatment of line-height in the inline box model.  For
359    // now (until the inline box model is re-written), this mode is identical to STANDARDS mode.
360    // STRICT - no quirks apply.  Web pages will obey the specifications to the letter.
361    bool wasInCompatMode = inCompatMode();
362    DocumentType* docType = doctype();
363    if (!docType || !equalIgnoringCase(docType->name(), "html"))
364        // No doctype found at all or the doctype is not HTML.  Default to quirks mode and Html4.
365        setParseMode(Compat);
366    else if (!doctype()->systemId().isEmpty() && equalIgnoringCase(docType->systemId(), "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"))
367        // Assume quirks mode for this particular system ID.  In the HTML5 spec, this is the only
368        // system identifier that is examined.
369        setParseMode(Compat);
370    else if (docType->publicId().isEmpty())
371        // A doctype without a public ID means use strict mode.
372        setParseMode(Strict);
373    else {
374        // We have to check a list of public IDs to see what we
375        // should do.
376        String lowerPubID = docType->publicId().lower();
377        CString pubIDStr = lowerPubID.latin1();
378       
379        // Look up the entry in our gperf-generated table.
380        const PubIDInfo* doctypeEntry = findDoctypeEntry(pubIDStr.data(), pubIDStr.length());
381        if (!doctypeEntry)
382            // The DOCTYPE is not in the list.  Assume strict mode.
383            setParseMode(Strict);
384        else {
385            switch (docType->systemId().isEmpty() ?
386                    doctypeEntry->mode_if_no_sysid :
387                    doctypeEntry->mode_if_sysid) {
388                case PubIDInfo::eQuirks3:
389                case PubIDInfo::eQuirks:
390                    setParseMode(Compat);
391                    break;
392                case PubIDInfo::eAlmostStandards:
393                    setParseMode(AlmostStrict);
394                    break;
395                 default:
396                    ASSERT(false);
397            }
398        }
399    }
400   
401    if (inCompatMode() != wasInCompatMode)
402        updateStyleSelector();
403}
404
405void HTMLDocument::clear()
406{
407    // FIXME: This does nothing, and that seems unlikely to be correct.
408    // We've long had a comment saying that IE doesn't support this.
409    // But I do see it in the documentation for Mozilla.
410}
411
412bool HTMLDocument::isFrameSet() const
413{
414    HTMLElement* bodyElement = body();
415    return bodyElement && bodyElement->renderer() && bodyElement->hasTagName(framesetTag);
416}
417
418}
Note: See TracBrowser for help on using the browser.