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