1/* 2 * Copyright (C) 2007, 2008, 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 "CSSFontFace.h" 28 29#include "CSSFontFaceSource.h" 30#include "CSSFontSelector.h" 31#include "CSSSegmentedFontFace.h" 32#include "Document.h" 33#include "FontDescription.h" 34#include "FontLoader.h" 35#include "RuntimeEnabledFeatures.h" 36#include "SimpleFontData.h" 37 38namespace WebCore { 39 40bool CSSFontFace::isLoaded() const 41{ 42 size_t size = m_sources.size(); 43 for (size_t i = 0; i < size; i++) { 44 if (!m_sources[i]->isLoaded()) 45 return false; 46 } 47 return true; 48} 49 50bool CSSFontFace::isValid() const 51{ 52 size_t size = m_sources.size(); 53 for (size_t i = 0; i < size; i++) { 54 if (m_sources[i]->isValid()) 55 return true; 56 } 57 return false; 58} 59 60void CSSFontFace::addedToSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace) 61{ 62 m_segmentedFontFaces.add(segmentedFontFace); 63} 64 65void CSSFontFace::removedFromSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace) 66{ 67 m_segmentedFontFaces.remove(segmentedFontFace); 68} 69 70void CSSFontFace::addSource(PassOwnPtr<CSSFontFaceSource> source) 71{ 72 source->setFontFace(this); 73 m_sources.append(source); 74} 75 76void CSSFontFace::fontLoaded(CSSFontFaceSource* source) 77{ 78 if (source != m_activeSource) 79 return; 80 81 // FIXME: Can we assert that m_segmentedFontFaces is not empty? That may 82 // require stopping in-progress font loading when the last 83 // CSSSegmentedFontFace is removed. 84 if (m_segmentedFontFaces.isEmpty()) 85 return; 86 87 // Use one of the CSSSegmentedFontFaces' font selector. They all have 88 // the same font selector, so it's wasteful to store it in the CSSFontFace. 89 CSSFontSelector* fontSelector = (*m_segmentedFontFaces.begin())->fontSelector(); 90 fontSelector->fontLoaded(); 91 92#if ENABLE(FONT_LOAD_EVENTS) 93 if (RuntimeEnabledFeatures::fontLoadEventsEnabled() && m_loadState == Loading) { 94 if (source->ensureFontData()) 95 notifyFontLoader(Loaded); 96 else if (!isValid()) 97 notifyFontLoader(Error); 98 } 99#endif 100 101 HashSet<CSSSegmentedFontFace*>::iterator end = m_segmentedFontFaces.end(); 102 for (HashSet<CSSSegmentedFontFace*>::iterator it = m_segmentedFontFaces.begin(); it != end; ++it) 103 (*it)->fontLoaded(this); 104 105#if ENABLE(FONT_LOAD_EVENTS) 106 if (RuntimeEnabledFeatures::fontLoadEventsEnabled()) 107 notifyLoadingDone(); 108#endif 109} 110 111PassRefPtr<SimpleFontData> CSSFontFace::getFontData(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic) 112{ 113 m_activeSource = 0; 114 if (!isValid()) 115 return 0; 116 117 ASSERT(!m_segmentedFontFaces.isEmpty()); 118 CSSFontSelector* fontSelector = (*m_segmentedFontFaces.begin())->fontSelector(); 119 120#if ENABLE(FONT_LOAD_EVENTS) 121 if (RuntimeEnabledFeatures::fontLoadEventsEnabled() && m_loadState == NotLoaded) 122 notifyFontLoader(Loading); 123#endif 124 125 size_t size = m_sources.size(); 126 for (size_t i = 0; i < size; ++i) { 127 if (RefPtr<SimpleFontData> result = m_sources[i]->getFontData(fontDescription, syntheticBold, syntheticItalic, fontSelector)) { 128 m_activeSource = m_sources[i].get(); 129#if ENABLE(FONT_LOAD_EVENTS) 130 if (RuntimeEnabledFeatures::fontLoadEventsEnabled() && m_loadState == Loading && m_sources[i]->isLoaded()) { 131 notifyFontLoader(Loaded); 132 notifyLoadingDone(); 133 } 134#endif 135 return result.release(); 136 } 137 } 138 139#if ENABLE(FONT_LOAD_EVENTS) 140 if (RuntimeEnabledFeatures::fontLoadEventsEnabled() && m_loadState == Loading) { 141 notifyFontLoader(Error); 142 notifyLoadingDone(); 143 } 144#endif 145 return 0; 146} 147 148#if ENABLE(FONT_LOAD_EVENTS) 149void CSSFontFace::notifyFontLoader(LoadState newState) 150{ 151 m_loadState = newState; 152 153 Document* document = (*m_segmentedFontFaces.begin())->fontSelector()->document(); 154 if (!document) 155 return; 156 157 switch (newState) { 158 case Loading: 159 document->fontloader()->beginFontLoading(m_rule.get()); 160 break; 161 case Loaded: 162 document->fontloader()->fontLoaded(m_rule.get()); 163 break; 164 case Error: 165 document->fontloader()->loadError(m_rule.get(), m_activeSource); 166 break; 167 default: 168 break; 169 } 170} 171 172void CSSFontFace::notifyLoadingDone() 173{ 174 Document* document = (*m_segmentedFontFaces.begin())->fontSelector()->document(); 175 if (document) 176 document->fontloader()->loadingDone(); 177} 178#endif 179 180#if ENABLE(SVG_FONTS) 181bool CSSFontFace::hasSVGFontFaceSource() const 182{ 183 size_t size = m_sources.size(); 184 for (size_t i = 0; i < size; i++) { 185 if (m_sources[i]->isSVGFontFaceSource()) 186 return true; 187 } 188 return false; 189} 190#endif 191 192} 193