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 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 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#include "CachedFontClient.h" 31#include "CachedResourceClientWalker.h" 32#include "CachedResourceLoader.h" 33#include "FontCustomPlatformData.h" 34#include "FontPlatformData.h" 35#include "MemoryCache.h" 36#include "ResourceBuffer.h" 37#include "SharedBuffer.h" 38#include "TextResourceDecoder.h" 39#include "TypedElementDescendantIterator.h" 40#include "WOFFFileFormat.h" 41#include <wtf/Vector.h> 42 43#if ENABLE(SVG_FONTS) 44#include "NodeList.h" 45#include "SVGDocument.h" 46#include "SVGElement.h" 47#include "SVGFontElement.h" 48#include "SVGGElement.h" 49#include "SVGNames.h" 50#endif 51 52namespace WebCore { 53 54CachedFont::CachedFont(const ResourceRequest& resourceRequest, SessionID sessionID) 55 : CachedResource(resourceRequest, FontResource, sessionID) 56 , m_loadInitiated(false) 57 , m_hasCreatedFontDataWrappingResource(false) 58{ 59} 60 61CachedFont::~CachedFont() 62{ 63} 64 65void CachedFont::load(CachedResourceLoader*, const ResourceLoaderOptions& options) 66{ 67 // Don't load the file yet. Wait for an access before triggering the load. 68 setLoading(true); 69 m_options = options; 70} 71 72void CachedFont::didAddClient(CachedResourceClient* c) 73{ 74 ASSERT(c->resourceClientType() == CachedFontClient::expectedType()); 75 if (!isLoading()) 76 static_cast<CachedFontClient*>(c)->fontLoaded(this); 77} 78 79void CachedFont::finishLoading(ResourceBuffer* data) 80{ 81 m_data = data; 82 setEncodedSize(m_data.get() ? m_data->size() : 0); 83 setLoading(false); 84 checkNotify(); 85} 86 87void CachedFont::beginLoadIfNeeded(CachedResourceLoader* dl) 88{ 89 if (!m_loadInitiated) { 90 m_loadInitiated = true; 91 CachedResource::load(dl, m_options); 92 } 93} 94 95bool CachedFont::ensureCustomFontData() 96{ 97 if (!m_fontData && !errorOccurred() && !isLoading() && m_data) { 98 SharedBuffer* buffer = m_data.get()->sharedBuffer(); 99 ASSERT(buffer); 100 101 RefPtr<SharedBuffer> sfntBuffer; 102 103 bool fontIsWOFF = isWOFF(buffer); 104 if (fontIsWOFF) { 105 Vector<char> sfnt; 106 if (convertWOFFToSfnt(buffer, sfnt)) { 107 sfntBuffer = SharedBuffer::adoptVector(sfnt); 108 buffer = sfntBuffer.get(); 109 } else 110 buffer = nullptr; 111 } 112 113 m_fontData = buffer ? createFontCustomPlatformData(*buffer) : nullptr; 114 if (m_fontData) 115 m_hasCreatedFontDataWrappingResource = !fontIsWOFF; 116 else 117 setStatus(DecodeError); 118 } 119 return m_fontData.get(); 120} 121 122FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode renderingMode) 123{ 124#if ENABLE(SVG_FONTS) 125 if (m_externalSVGDocument) 126 return FontPlatformData(size, bold, italic); 127#endif 128 ASSERT(m_fontData); 129 return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, orientation, widthVariant, renderingMode); 130} 131 132#if ENABLE(SVG_FONTS) 133 134bool CachedFont::ensureSVGFontData() 135{ 136 if (!m_externalSVGDocument && !errorOccurred() && !isLoading() && m_data) { 137 m_externalSVGDocument = SVGDocument::create(nullptr, URL()); 138 RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml"); 139 m_externalSVGDocument->setContent(decoder->decodeAndFlush(m_data->data(), m_data->size())); 140 if (decoder->sawError()) 141 m_externalSVGDocument = nullptr; 142 } 143 return m_externalSVGDocument; 144} 145 146SVGFontElement* CachedFont::getSVGFontById(const String& fontName) const 147{ 148 auto elements = descendantsOfType<SVGFontElement>(*m_externalSVGDocument); 149 150 if (fontName.isEmpty()) 151 return elements.first(); 152 153 for (auto& element : elements) { 154 if (element.getIdAttribute() == fontName) 155 return &element; 156 } 157 return nullptr; 158} 159 160#endif 161 162void CachedFont::allClientsRemoved() 163{ 164 m_fontData = nullptr; 165} 166 167void CachedFont::checkNotify() 168{ 169 if (isLoading()) 170 return; 171 172 CachedResourceClientWalker<CachedFontClient> w(m_clients); 173 while (CachedFontClient* c = w.next()) 174 c->fontLoaded(this); 175} 176 177bool CachedFont::mayTryReplaceEncodedData() const 178{ 179 // If a FontCustomPlatformData has ever been constructed to wrap the internal resource buffer then it still might be in use somewhere. 180 // That platform font object might directly reference the encoded data buffer behind this CachedFont, 181 // so replacing it is unsafe. 182 183 return !m_hasCreatedFontDataWrappingResource; 184} 185 186} 187