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 "core/fetch/FontResource.h" 29 30 #include "core/fetch/ResourceClientWalker.h" 31 #include "core/fetch/TextResourceDecoder.h" 32 #include "platform/SharedBuffer.h" 33 #include "platform/fonts/FontCustomPlatformData.h" 34 #include "platform/fonts/FontPlatformData.h" 35 #include "public/platform/Platform.h" 36 #include "wtf/CurrentTime.h" 37 38 #if ENABLE(SVG_FONTS) 39 #include "SVGNames.h" 40 #include "core/dom/NodeList.h" 41 #include "core/svg/SVGDocument.h" 42 #include "core/svg/SVGFontElement.h" 43 #endif 44 45 namespace WebCore { 46 47 FontResource::FontResource(const ResourceRequest& resourceRequest) 48 : Resource(resourceRequest, Font) 49 , m_loadInitiated(false) 50 { 51 } 52 53 FontResource::~FontResource() 54 { 55 } 56 57 void FontResource::load(ResourceFetcher*, const ResourceLoaderOptions& options) 58 { 59 // Don't load the file yet. Wait for an access before triggering the load. 60 setLoading(true); 61 m_options = options; 62 } 63 64 void FontResource::didAddClient(ResourceClient* c) 65 { 66 ASSERT(c->resourceClientType() == FontResourceClient::expectedType()); 67 Resource::didAddClient(c); 68 if (!isLoading()) 69 static_cast<FontResourceClient*>(c)->fontLoaded(this); 70 } 71 72 void FontResource::beginLoadIfNeeded(ResourceFetcher* dl) 73 { 74 if (!m_loadInitiated) { 75 m_loadInitiated = true; 76 Resource::load(dl, m_options); 77 78 ResourceClientWalker<FontResourceClient> walker(m_clients); 79 while (FontResourceClient* client = walker.next()) 80 client->didStartFontLoad(this); 81 } 82 } 83 84 bool FontResource::ensureCustomFontData() 85 { 86 if (!m_fontData && !errorOccurred() && !isLoading()) { 87 if (m_data) 88 m_fontData = FontCustomPlatformData::create(m_data.get()); 89 if (!m_fontData) 90 setStatus(DecodeError); 91 } 92 return m_fontData; 93 } 94 95 FontPlatformData FontResource::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant) 96 { 97 #if ENABLE(SVG_FONTS) 98 if (m_externalSVGDocument) 99 return FontPlatformData(size, bold, italic); 100 #endif 101 ASSERT(m_fontData); 102 return m_fontData->fontPlatformData(size, bold, italic, orientation, widthVariant); 103 } 104 105 #if ENABLE(SVG_FONTS) 106 bool FontResource::ensureSVGFontData() 107 { 108 if (!m_externalSVGDocument && !errorOccurred() && !isLoading()) { 109 if (m_data) { 110 m_externalSVGDocument = SVGDocument::create(); 111 112 OwnPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml"); 113 String svgSource = decoder->decode(m_data->data(), m_data->size()); 114 svgSource.append(decoder->flush()); 115 116 m_externalSVGDocument->setContent(svgSource); 117 118 if (decoder->sawError()) 119 m_externalSVGDocument = 0; 120 } 121 if (!m_externalSVGDocument) 122 setStatus(DecodeError); 123 } 124 125 return m_externalSVGDocument; 126 } 127 128 SVGFontElement* FontResource::getSVGFontById(const String& fontName) const 129 { 130 RefPtr<NodeList> list = m_externalSVGDocument->getElementsByTagNameNS(SVGNames::fontTag.namespaceURI(), SVGNames::fontTag.localName()); 131 if (!list) 132 return 0; 133 134 unsigned listLength = list->length(); 135 if (!listLength) 136 return 0; 137 138 #ifndef NDEBUG 139 for (unsigned i = 0; i < listLength; ++i) { 140 ASSERT(list->item(i)); 141 ASSERT(list->item(i)->hasTagName(SVGNames::fontTag)); 142 } 143 #endif 144 145 if (fontName.isEmpty()) 146 return toSVGFontElement(list->item(0)); 147 148 for (unsigned i = 0; i < listLength; ++i) { 149 SVGFontElement* element = toSVGFontElement(list->item(i)); 150 if (element->getIdAttribute() == fontName) 151 return element; 152 } 153 154 return 0; 155 } 156 #endif 157 158 void FontResource::allClientsRemoved() 159 { 160 m_fontData.clear(); 161 Resource::allClientsRemoved(); 162 } 163 164 void FontResource::checkNotify() 165 { 166 ResourceClientWalker<FontResourceClient> w(m_clients); 167 while (FontResourceClient* c = w.next()) 168 c->fontLoaded(this); 169 } 170 171 } 172