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