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