1/* 2 * Copyright (C) 2007, 2008, 2010, 2011 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 "CSSFontFaceSource.h" 28 29#include "CachedFont.h" 30#include "CSSFontFace.h" 31#include "CSSFontSelector.h" 32#include "CachedResourceLoader.h" 33#include "Document.h" 34#include "FontCache.h" 35#include "FontDescription.h" 36#include "SimpleFontData.h" 37 38#if ENABLE(SVG_FONTS) 39#include "FontCustomPlatformData.h" 40#include "SVGFontData.h" 41#include "SVGFontElement.h" 42#include "SVGFontFaceElement.h" 43#include "SVGNames.h" 44#include "SVGURIReference.h" 45#endif 46 47namespace WebCore { 48 49CSSFontFaceSource::CSSFontFaceSource(const String& str, CachedFont* font) 50 : m_string(str) 51 , m_font(font) 52 , m_face(0) 53#if ENABLE(SVG_FONTS) 54 , m_hasExternalSVGFont(false) 55#endif 56{ 57 if (m_font) 58 m_font->addClient(this); 59} 60 61CSSFontFaceSource::~CSSFontFaceSource() 62{ 63 if (m_font) 64 m_font->removeClient(this); 65 pruneTable(); 66} 67 68void CSSFontFaceSource::pruneTable() 69{ 70 if (m_fontDataTable.isEmpty()) 71 return; 72 73 m_fontDataTable.clear(); 74} 75 76bool CSSFontFaceSource::isLoaded() const 77{ 78 if (m_font) 79 return m_font->isLoaded(); 80 return true; 81} 82 83bool CSSFontFaceSource::isValid() const 84{ 85 if (m_font) 86 return !m_font->errorOccurred(); 87 return true; 88} 89 90void CSSFontFaceSource::fontLoaded(CachedFont*) 91{ 92 pruneTable(); 93 if (m_face) 94 m_face->fontLoaded(this); 95} 96 97PassRefPtr<SimpleFontData> CSSFontFaceSource::getFontData(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, CSSFontSelector* fontSelector) 98{ 99 // If the font hasn't loaded or an error occurred, then we've got nothing. 100 if (!isValid()) 101 return 0; 102 103 if (!m_font 104#if ENABLE(SVG_FONTS) 105 && !m_svgFontFaceElement 106#endif 107 ) { 108 // We're local. Just return a SimpleFontData from the normal cache. 109 // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter. 110 return fontCache()->getCachedFontData(fontDescription, m_string, true); 111 } 112 113 // See if we have a mapping in our FontData cache. 114 unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 5 | fontDescription.widthVariant() << 3 115 | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0); 116 117 RefPtr<SimpleFontData>& fontData = m_fontDataTable.add(hashKey, 0).iterator->value; 118 if (fontData) 119 return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable. 120 121 // If we are still loading, then we let the system pick a font. 122 if (isLoaded()) { 123 if (m_font) { 124#if ENABLE(SVG_FONTS) 125 if (m_hasExternalSVGFont) { 126 // For SVG fonts parse the external SVG document, and extract the <font> element. 127 if (!m_font->ensureSVGFontData()) 128 return 0; 129 130 if (!m_externalSVGFontElement) { 131 String fragmentIdentifier; 132 size_t start = m_string.find('#'); 133 if (start != notFound) 134 fragmentIdentifier = m_string.string().substring(start + 1); 135 m_externalSVGFontElement = m_font->getSVGFontById(fragmentIdentifier); 136 } 137 138 if (!m_externalSVGFontElement) 139 return 0; 140 141 SVGFontFaceElement* fontFaceElement = 0; 142 143 // Select first <font-face> child 144 for (Node* fontChild = m_externalSVGFontElement->firstChild(); fontChild; fontChild = fontChild->nextSibling()) { 145 if (fontChild->hasTagName(SVGNames::font_faceTag)) { 146 fontFaceElement = static_cast<SVGFontFaceElement*>(fontChild); 147 break; 148 } 149 } 150 151 if (fontFaceElement) { 152 if (!m_svgFontFaceElement) { 153 // We're created using a CSS @font-face rule, that means we're not associated with a SVGFontFaceElement. 154 // Use the imported <font-face> tag as referencing font-face element for these cases. 155 m_svgFontFaceElement = fontFaceElement; 156 } 157 158 fontData = SimpleFontData::create(SVGFontData::create(fontFaceElement), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic); 159 } 160 } else 161#endif 162 { 163 // Create new FontPlatformData from our CGFontRef, point size and ATSFontRef. 164 if (!m_font->ensureCustomFontData()) 165 return 0; 166 167 fontData = SimpleFontData::create(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, 168 fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.renderingMode()), true, false); 169 } 170 } else { 171#if ENABLE(SVG_FONTS) 172 // In-Document SVG Fonts 173 if (m_svgFontFaceElement) 174 fontData = SimpleFontData::create(SVGFontData::create(m_svgFontFaceElement.get()), fontDescription.computedPixelSize(), syntheticBold, syntheticItalic); 175#endif 176 } 177 } else { 178 // Kick off the load. Do it soon rather than now, because we may be in the middle of layout, 179 // and the loader may invoke arbitrary delegate or event handler code. 180 fontSelector->beginLoadingFontSoon(m_font.get()); 181 182 // This temporary font is not retained and should not be returned. 183 FontCachePurgePreventer fontCachePurgePreventer; 184 SimpleFontData* temporaryFont = fontCache()->getNonRetainedLastResortFallbackFont(fontDescription); 185 fontData = SimpleFontData::create(temporaryFont->platformData(), true, true); 186 } 187 188 return fontData; // No release, because fontData is a reference to a RefPtr that is held in the m_fontDataTable. 189} 190 191#if ENABLE(SVG_FONTS) 192SVGFontFaceElement* CSSFontFaceSource::svgFontFaceElement() const 193{ 194 return m_svgFontFaceElement.get(); 195} 196 197void CSSFontFaceSource::setSVGFontFaceElement(PassRefPtr<SVGFontFaceElement> element) 198{ 199 m_svgFontFaceElement = element; 200} 201 202bool CSSFontFaceSource::isSVGFontFaceSource() const 203{ 204 return m_svgFontFaceElement || m_hasExternalSVGFont; 205} 206#endif 207 208#if ENABLE(FONT_LOAD_EVENTS) 209bool CSSFontFaceSource::isDecodeError() const 210{ 211 if (m_font) 212 return m_font->status() == CachedResource::DecodeError; 213 return false; 214} 215 216bool CSSFontFaceSource::ensureFontData() 217{ 218 if (!m_font) 219 return false; 220#if ENABLE(SVG_FONTS) 221 if (m_hasExternalSVGFont) 222 return m_font->ensureSVGFontData(); 223#endif 224 return m_font->ensureCustomFontData(); 225} 226#endif 227 228} 229