19eb3bac28105e50b77ed7fe7a8190e4e97acabf
[WebKit-https.git] / Source / WebCore / loader / cache / CachedFont.cpp
1 /*
2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3  * Copyright (C) 2009 Torch Mobile, Inc.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
25  */
26
27 #include "config.h"
28 #include "CachedFont.h"
29
30 #if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (OS(WINDOWS) || OS(LINUX) || OS(FREEBSD))) || PLATFORM(HAIKU) || OS(WINCE) || PLATFORM(ANDROID) || PLATFORM(BREWMP)
31 #define STORE_FONT_CUSTOM_PLATFORM_DATA
32 #endif
33
34 #include "CachedResourceClient.h"
35 #include "CachedResourceClientWalker.h"
36 #include "CachedResourceLoader.h"
37 #include "FontPlatformData.h"
38 #include "MemoryCache.h"
39 #include "SharedBuffer.h"
40 #include "TextResourceDecoder.h"
41 #include <wtf/Vector.h>
42
43 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
44 #include "FontCustomPlatformData.h"
45 #endif
46
47 #if ENABLE(SVG_FONTS)
48 #include "NodeList.h"
49 #include "SVGElement.h"
50 #include "SVGFontElement.h"
51 #include "SVGGElement.h"
52 #include "SVGNames.h"
53 #endif
54
55 namespace WebCore {
56
57 CachedFont::CachedFont(const String &url)
58     : CachedResource(url, FontResource)
59     , m_fontData(0)
60     , m_loadInitiated(false)
61 #if ENABLE(SVG_FONTS)
62     , m_isSVGFont(false)
63 #endif
64 {
65 }
66
67 CachedFont::~CachedFont()
68 {
69 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
70     delete m_fontData;
71 #endif
72 }
73
74 void CachedFont::load(CachedResourceLoader*)
75 {
76     // Don't load the file yet.  Wait for an access before triggering the load.
77     setLoading(true);
78 }
79
80 void CachedFont::didAddClient(CachedResourceClient* c)
81 {
82     if (!isLoading())
83         c->fontLoaded(this);
84 }
85
86 void CachedFont::data(PassRefPtr<SharedBuffer> data, bool allDataReceived)
87 {
88     if (!allDataReceived)
89         return;
90
91     m_data = data;     
92     setEncodedSize(m_data.get() ? m_data->size() : 0);
93     setLoading(false);
94     checkNotify();
95 }
96
97 void CachedFont::beginLoadIfNeeded(CachedResourceLoader* dl)
98 {
99     if (!m_loadInitiated) {
100         m_loadInitiated = true;
101         dl->load(this, false);
102     }
103 }
104
105 bool CachedFont::ensureCustomFontData()
106 {
107 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
108 #if ENABLE(SVG_FONTS)
109     ASSERT(!m_isSVGFont);
110 #endif
111     if (!m_fontData && !errorOccurred() && !isLoading() && m_data) {
112         m_fontData = createFontCustomPlatformData(m_data.get());
113         if (!m_fontData)
114             setStatus(DecodeError);
115     }
116 #endif
117     return m_fontData;
118 }
119
120 FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode renderingMode)
121 {
122 #if ENABLE(SVG_FONTS)
123     if (m_externalSVGDocument)
124         return FontPlatformData(size, bold, italic);
125 #endif
126 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
127     ASSERT(m_fontData);
128     return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, orientation, widthVariant, renderingMode);
129 #else
130     return FontPlatformData();
131 #endif
132 }
133
134 #if ENABLE(SVG_FONTS)
135 bool CachedFont::ensureSVGFontData()
136 {
137     ASSERT(m_isSVGFont);
138     if (!m_externalSVGDocument && !errorOccurred() && !isLoading() && m_data) {
139         m_externalSVGDocument = SVGDocument::create(0, KURL());
140
141         RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml");
142
143         m_externalSVGDocument->setContent(decoder->decode(m_data->data(), m_data->size()) + decoder->flush());
144         
145         if (decoder->sawError())
146             m_externalSVGDocument = 0;
147     }
148
149     return m_externalSVGDocument;
150 }
151
152 SVGFontElement* CachedFont::getSVGFontById(const String& fontName) const
153 {
154     ASSERT(m_isSVGFont);
155     RefPtr<NodeList> list = m_externalSVGDocument->getElementsByTagNameNS(SVGNames::fontTag.namespaceURI(), SVGNames::fontTag.localName());
156     if (!list)
157         return 0;
158
159     unsigned listLength = list->length();
160     if (!listLength)
161         return 0;
162
163 #ifndef NDEBUG
164     for (unsigned i = 0; i < listLength; ++i) {
165         ASSERT(list->item(i));
166         ASSERT(list->item(i)->hasTagName(SVGNames::fontTag));
167     }
168 #endif
169
170     if (fontName.isEmpty())
171         return static_cast<SVGFontElement*>(list->item(0));
172
173     for (unsigned i = 0; i < listLength; ++i) {
174         SVGFontElement* element = static_cast<SVGFontElement*>(list->item(i));
175         if (element->getIdAttribute() == fontName)
176             return element;
177     }
178
179     return 0;
180 }
181 #endif
182
183 void CachedFont::allClientsRemoved()
184 {
185 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
186     if (m_fontData) {
187         delete m_fontData;
188         m_fontData = 0;
189     }
190 #endif
191 }
192
193 void CachedFont::checkNotify()
194 {
195     if (isLoading())
196         return;
197     
198     CachedResourceClientWalker w(m_clients);
199     while (CachedResourceClient *c = w.next())
200          c->fontLoaded(this);
201 }
202
203
204 void CachedFont::error(CachedResource::Status status)
205 {
206     setStatus(status);
207     ASSERT(errorOccurred());
208     setLoading(false);
209     checkNotify();
210 }
211
212 }