1 /*
2 * Copyright (C) 2006, 2007 Rob Buis
3 * Copyright (C) 2008 Apple, Inc. All rights reserved.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22 #include "StyleElement.h"
23
24 #include "Document.h"
25 #include "Element.h"
26 #include "MappedAttribute.h"
27 #include "MediaList.h"
28 #include "MediaQueryEvaluator.h"
29
30 namespace WebCore {
31
StyleElement()32 StyleElement::StyleElement()
33 {
34 }
35
sheet(Element * e)36 StyleSheet* StyleElement::sheet(Element* e)
37 {
38 if (!m_sheet)
39 createSheet(e);
40 return m_sheet.get();
41 }
42
insertedIntoDocument(Document *,Element * element)43 void StyleElement::insertedIntoDocument(Document*, Element* element)
44 {
45 process(element);
46 }
47
removedFromDocument(Document * document)48 void StyleElement::removedFromDocument(Document* document)
49 {
50 // If we're in document teardown, then we don't need to do any notification of our sheet's removal.
51 if (!document->renderer())
52 return;
53
54 // FIXME: It's terrible to do a synchronous update of the style selector just because a <style> or <link> element got removed.
55 if (m_sheet)
56 document->updateStyleSelector();
57 }
58
process(Element * e)59 void StyleElement::process(Element* e)
60 {
61 if (!e || !e->inDocument())
62 return;
63
64 unsigned resultLength = 0;
65 for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
66 Node::NodeType nodeType = c->nodeType();
67 if (nodeType == Node::TEXT_NODE || nodeType == Node::CDATA_SECTION_NODE || nodeType == Node::COMMENT_NODE)
68 resultLength += c->nodeValue().length();
69 }
70 UChar* text;
71 String sheetText = String::createUninitialized(resultLength, text);
72
73 UChar* p = text;
74 for (Node* c = e->firstChild(); c; c = c->nextSibling()) {
75 Node::NodeType nodeType = c->nodeType();
76 if (nodeType == Node::TEXT_NODE || nodeType == Node::CDATA_SECTION_NODE || nodeType == Node::COMMENT_NODE) {
77 String nodeValue = c->nodeValue();
78 unsigned nodeLength = nodeValue.length();
79 memcpy(p, nodeValue.characters(), nodeLength * sizeof(UChar));
80 p += nodeLength;
81 }
82 }
83 ASSERT(p == text + resultLength);
84
85 createSheet(e, sheetText);
86 }
87
createSheet(Element * e,const String & text)88 void StyleElement::createSheet(Element* e, const String& text)
89 {
90 Document* document = e->document();
91 if (m_sheet) {
92 if (static_cast<CSSStyleSheet*>(m_sheet.get())->isLoading())
93 document->removePendingSheet();
94 m_sheet = 0;
95 }
96
97 // If type is empty or CSS, this is a CSS style sheet.
98 const AtomicString& type = this->type();
99 if (type.isEmpty() || (e->isHTMLElement() ? equalIgnoringCase(type, "text/css") : (type == "text/css"))) {
100 RefPtr<MediaList> mediaList = MediaList::create(media(), e->isHTMLElement());
101 MediaQueryEvaluator screenEval("screen", true);
102 MediaQueryEvaluator printEval("print", true);
103 if (screenEval.eval(mediaList.get()) || printEval.eval(mediaList.get())) {
104 document->addPendingSheet();
105 setLoading(true);
106 m_sheet = CSSStyleSheet::create(e, String(), document->inputEncoding());
107 m_sheet->parseString(text, !document->inCompatMode());
108 m_sheet->setMedia(mediaList.get());
109 m_sheet->setTitle(e->title());
110 setLoading(false);
111 }
112 }
113
114 if (m_sheet)
115 m_sheet->checkLoaded();
116 }
117
118 }
119