Home | History | Annotate | Download | only in css
      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 "core/css/CSSFontFace.h"
     28 
     29 #include "core/css/CSSFontFaceSource.h"
     30 #include "core/css/CSSFontSelector.h"
     31 #include "core/css/CSSSegmentedFontFace.h"
     32 #include "core/css/FontFaceSet.h"
     33 #include "core/css/RemoteFontFaceSource.h"
     34 #include "core/dom/Document.h"
     35 #include "core/frame/UseCounter.h"
     36 #include "platform/fonts/FontDescription.h"
     37 #include "platform/fonts/SimpleFontData.h"
     38 
     39 namespace WebCore {
     40 
     41 void CSSFontFace::addSource(PassOwnPtrWillBeRawPtr<CSSFontFaceSource> source)
     42 {
     43     source->setFontFace(this);
     44     m_sources.append(source);
     45 }
     46 
     47 void CSSFontFace::setSegmentedFontFace(CSSSegmentedFontFace* segmentedFontFace)
     48 {
     49     ASSERT(!m_segmentedFontFace);
     50     m_segmentedFontFace = segmentedFontFace;
     51 }
     52 
     53 void CSSFontFace::didBeginLoad()
     54 {
     55     if (loadStatus() == FontFace::Unloaded)
     56         setLoadStatus(FontFace::Loading);
     57 }
     58 
     59 void CSSFontFace::fontLoaded(RemoteFontFaceSource* source)
     60 {
     61     if (!isValid() || source != m_sources.first())
     62         return;
     63 
     64     if (loadStatus() == FontFace::Loading) {
     65         if (source->ensureFontData()) {
     66             setLoadStatus(FontFace::Loaded);
     67 #if ENABLE(SVG_FONTS)
     68             Document* document = m_segmentedFontFace ? m_segmentedFontFace->fontSelector()->document() : 0;
     69             if (document && source->isSVGFontFaceSource())
     70                 UseCounter::count(*document, UseCounter::SVGFontInCSS);
     71 #endif
     72         } else {
     73             m_sources.removeFirst();
     74             load();
     75         }
     76     }
     77 
     78     if (m_segmentedFontFace)
     79         m_segmentedFontFace->fontLoaded(this);
     80 }
     81 
     82 void CSSFontFace::fontLoadWaitLimitExceeded(RemoteFontFaceSource* source)
     83 {
     84     if (!isValid() || source != m_sources.first())
     85         return;
     86     if (m_segmentedFontFace)
     87         m_segmentedFontFace->fontLoadWaitLimitExceeded(this);
     88 }
     89 
     90 PassRefPtr<SimpleFontData> CSSFontFace::getFontData(const FontDescription& fontDescription)
     91 {
     92     if (!isValid())
     93         return nullptr;
     94 
     95     while (!m_sources.isEmpty()) {
     96         OwnPtrWillBeMember<CSSFontFaceSource>& source = m_sources.first();
     97         if (RefPtr<SimpleFontData> result = source->getFontData(fontDescription)) {
     98             if (loadStatus() == FontFace::Unloaded && (source->isLoading() || source->isLoaded()))
     99                 setLoadStatus(FontFace::Loading);
    100             if (loadStatus() == FontFace::Loading && source->isLoaded())
    101                 setLoadStatus(FontFace::Loaded);
    102             return result.release();
    103         }
    104         m_sources.removeFirst();
    105     }
    106 
    107     if (loadStatus() == FontFace::Unloaded)
    108         setLoadStatus(FontFace::Loading);
    109     if (loadStatus() == FontFace::Loading)
    110         setLoadStatus(FontFace::Error);
    111     return nullptr;
    112 }
    113 
    114 bool CSSFontFace::maybeScheduleFontLoad(const FontDescription& fontDescription, UChar32 character)
    115 {
    116     if (m_ranges.contains(character)) {
    117         if (loadStatus() == FontFace::Unloaded)
    118             load(fontDescription);
    119         return true;
    120     }
    121     return false;
    122 }
    123 
    124 void CSSFontFace::load()
    125 {
    126     FontDescription fontDescription;
    127     FontFamily fontFamily;
    128     fontFamily.setFamily(m_fontFace->family());
    129     fontDescription.setFamily(fontFamily);
    130     fontDescription.setTraits(m_fontFace->traits());
    131     load(fontDescription);
    132 }
    133 
    134 void CSSFontFace::load(const FontDescription& fontDescription)
    135 {
    136     if (loadStatus() == FontFace::Unloaded)
    137         setLoadStatus(FontFace::Loading);
    138     ASSERT(loadStatus() == FontFace::Loading);
    139 
    140     while (!m_sources.isEmpty()) {
    141         OwnPtrWillBeMember<CSSFontFaceSource>& source = m_sources.first();
    142         if (source->isValid()) {
    143             if (source->isLocal()) {
    144                 if (source->isLocalFontAvailable(fontDescription)) {
    145                     setLoadStatus(FontFace::Loaded);
    146                     return;
    147                 }
    148             } else {
    149                 if (!source->isLoaded())
    150                     source->beginLoadIfNeeded();
    151                 else
    152                     setLoadStatus(FontFace::Loaded);
    153                 return;
    154             }
    155         }
    156         m_sources.removeFirst();
    157     }
    158     setLoadStatus(FontFace::Error);
    159 }
    160 
    161 void CSSFontFace::setLoadStatus(FontFace::LoadStatus newStatus)
    162 {
    163     ASSERT(m_fontFace);
    164     m_fontFace->setLoadStatus(newStatus);
    165 
    166     if (!m_segmentedFontFace)
    167         return;
    168     Document* document = m_segmentedFontFace->fontSelector()->document();
    169     if (!document)
    170         return;
    171 
    172     switch (newStatus) {
    173     case FontFace::Loading:
    174         FontFaceSet::from(*document)->beginFontLoading(m_fontFace);
    175         break;
    176     case FontFace::Loaded:
    177         FontFaceSet::from(*document)->fontLoaded(m_fontFace);
    178         break;
    179     case FontFace::Error:
    180         FontFaceSet::from(*document)->loadError(m_fontFace);
    181         break;
    182     default:
    183         break;
    184     }
    185 }
    186 
    187 CSSFontFace::UnicodeRangeSet::UnicodeRangeSet(const Vector<UnicodeRange>& ranges)
    188     : m_ranges(ranges)
    189 {
    190     if (m_ranges.isEmpty())
    191         return;
    192 
    193     std::sort(m_ranges.begin(), m_ranges.end());
    194 
    195     // Unify overlapping ranges.
    196     UChar32 from = m_ranges[0].from();
    197     UChar32 to = m_ranges[0].to();
    198     size_t targetIndex = 0;
    199     for (size_t i = 1; i < m_ranges.size(); i++) {
    200         if (to + 1 >= m_ranges[i].from()) {
    201             to = std::max(to, m_ranges[i].to());
    202         } else {
    203             m_ranges[targetIndex++] = UnicodeRange(from, to);
    204             from = m_ranges[i].from();
    205             to = m_ranges[i].to();
    206         }
    207     }
    208     m_ranges[targetIndex++] = UnicodeRange(from, to);
    209     m_ranges.shrink(targetIndex);
    210 }
    211 
    212 bool CSSFontFace::UnicodeRangeSet::contains(UChar32 c) const
    213 {
    214     if (isEntireRange())
    215         return true;
    216     Vector<UnicodeRange>::const_iterator it = std::lower_bound(m_ranges.begin(), m_ranges.end(), c);
    217     return it != m_ranges.end() && it->contains(c);
    218 }
    219 
    220 bool CSSFontFace::UnicodeRangeSet::intersectsWith(const String& text) const
    221 {
    222     if (text.isEmpty())
    223         return false;
    224     if (isEntireRange())
    225         return true;
    226     if (text.is8Bit() && m_ranges[0].from() >= 0x100)
    227         return false;
    228 
    229     unsigned index = 0;
    230     while (index < text.length()) {
    231         UChar32 c = text.characterStartingAt(index);
    232         index += U16_LENGTH(c);
    233         if (contains(c))
    234             return true;
    235     }
    236     return false;
    237 }
    238 
    239 void CSSFontFace::trace(Visitor* visitor)
    240 {
    241     visitor->trace(m_segmentedFontFace);
    242     visitor->trace(m_sources);
    243     visitor->trace(m_fontFace);
    244 }
    245 
    246 }
    247