Home | History | Annotate | Download | only in css
      1 /*
      2  * Copyright (C) 2013 Google 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 are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "core/css/FontFace.h"
     33 
     34 #include "bindings/v8/Dictionary.h"
     35 #include "bindings/v8/ExceptionState.h"
     36 #include "bindings/v8/ScriptPromiseResolverWithContext.h"
     37 #include "bindings/v8/ScriptState.h"
     38 #include "core/CSSValueKeywords.h"
     39 #include "core/css/BinaryDataFontFaceSource.h"
     40 #include "core/css/CSSFontFace.h"
     41 #include "core/css/CSSFontFaceSrcValue.h"
     42 #include "core/css/CSSFontSelector.h"
     43 #include "core/css/CSSPrimitiveValue.h"
     44 #include "core/css/CSSUnicodeRangeValue.h"
     45 #include "core/css/CSSValueList.h"
     46 #include "core/css/LocalFontFaceSource.h"
     47 #include "core/css/RemoteFontFaceSource.h"
     48 #include "core/css/StylePropertySet.h"
     49 #include "core/css/StyleRule.h"
     50 #include "core/css/parser/BisonCSSParser.h"
     51 #include "core/dom/DOMError.h"
     52 #include "core/dom/Document.h"
     53 #include "core/dom/ExceptionCode.h"
     54 #include "core/dom/StyleEngine.h"
     55 #include "core/frame/LocalFrame.h"
     56 #include "core/frame/Settings.h"
     57 #include "core/svg/SVGFontFaceElement.h"
     58 #include "core/svg/SVGFontFaceSource.h"
     59 #include "core/svg/SVGRemoteFontFaceSource.h"
     60 #include "platform/FontFamilyNames.h"
     61 #include "platform/SharedBuffer.h"
     62 
     63 namespace WebCore {
     64 
     65 class FontFaceReadyPromiseResolver {
     66 public:
     67     static PassOwnPtr<FontFaceReadyPromiseResolver> create(ScriptState* scriptState)
     68     {
     69         return adoptPtr(new FontFaceReadyPromiseResolver(scriptState));
     70     }
     71 
     72     void resolve(PassRefPtrWillBeRawPtr<FontFace> fontFace)
     73     {
     74         switch (fontFace->loadStatus()) {
     75         case FontFace::Loaded:
     76             m_resolver->resolve(fontFace);
     77             break;
     78         case FontFace::Error:
     79             m_resolver->reject(fontFace->error());
     80             break;
     81         default:
     82             ASSERT_NOT_REACHED();
     83         }
     84     }
     85 
     86     ScriptPromise promise() { return m_resolver->promise(); }
     87 
     88 private:
     89     FontFaceReadyPromiseResolver(ScriptState* scriptState)
     90         : m_resolver(ScriptPromiseResolverWithContext::create(scriptState))
     91     {
     92     }
     93 
     94     RefPtr<ScriptPromiseResolverWithContext> m_resolver;
     95 };
     96 
     97 static PassRefPtrWillBeRawPtr<CSSValue> parseCSSValue(const Document* document, const String& s, CSSPropertyID propertyID)
     98 {
     99     if (s.isEmpty())
    100         return nullptr;
    101     RefPtrWillBeRawPtr<MutableStylePropertySet> parsedStyle = MutableStylePropertySet::create();
    102     BisonCSSParser::parseValue(parsedStyle.get(), propertyID, s, true, *document);
    103     return parsedStyle->getPropertyCSSValue(propertyID);
    104 }
    105 
    106 static bool initFontFace(FontFace* fontFace, ExecutionContext* context, const AtomicString& family, const Dictionary& descriptors, ExceptionState& exceptionState)
    107 {
    108     fontFace->setFamily(context, family, exceptionState);
    109     if (exceptionState.hadException())
    110         return false;
    111 
    112     String value;
    113     if (descriptors.get("style", value)) {
    114         fontFace->setStyle(context, value, exceptionState);
    115         if (exceptionState.hadException())
    116             return false;
    117     }
    118     if (descriptors.get("weight", value)) {
    119         fontFace->setWeight(context, value, exceptionState);
    120         if (exceptionState.hadException())
    121             return false;
    122     }
    123     if (descriptors.get("stretch", value)) {
    124         fontFace->setStretch(context, value, exceptionState);
    125         if (exceptionState.hadException())
    126             return false;
    127     }
    128     if (descriptors.get("unicodeRange", value)) {
    129         fontFace->setUnicodeRange(context, value, exceptionState);
    130         if (exceptionState.hadException())
    131             return false;
    132     }
    133     if (descriptors.get("variant", value)) {
    134         fontFace->setVariant(context, value, exceptionState);
    135         if (exceptionState.hadException())
    136             return false;
    137     }
    138     if (descriptors.get("featureSettings", value)) {
    139         fontFace->setFeatureSettings(context, value, exceptionState);
    140         if (exceptionState.hadException())
    141             return false;
    142     }
    143     return true;
    144 }
    145 
    146 PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, const String& source, const Dictionary& descriptors, ExceptionState& exceptionState)
    147 {
    148     RefPtrWillBeRawPtr<CSSValue> src = parseCSSValue(toDocument(context), source, CSSPropertySrc);
    149     if (!src || !src->isValueList()) {
    150         exceptionState.throwDOMException(SyntaxError, "The source provided ('" + source + "') could not be parsed as a value list.");
    151         return nullptr;
    152     }
    153 
    154     RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace());
    155     if (initFontFace(fontFace.get(), context, family, descriptors, exceptionState))
    156         fontFace->initCSSFontFace(toDocument(context), src);
    157     return fontFace.release();
    158 }
    159 
    160 PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, PassRefPtr<ArrayBuffer> source, const Dictionary& descriptors, ExceptionState& exceptionState)
    161 {
    162     RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace());
    163     if (initFontFace(fontFace.get(), context, family, descriptors, exceptionState))
    164         fontFace->initCSSFontFace(static_cast<const unsigned char*>(source->data()), source->byteLength());
    165     return fontFace.release();
    166 }
    167 
    168 PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, PassRefPtr<ArrayBufferView> source, const Dictionary& descriptors, ExceptionState& exceptionState)
    169 {
    170     RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace());
    171     if (initFontFace(fontFace.get(), context, family, descriptors, exceptionState))
    172         fontFace->initCSSFontFace(static_cast<const unsigned char*>(source->baseAddress()), source->byteLength());
    173     return fontFace.release();
    174 }
    175 
    176 PassRefPtrWillBeRawPtr<FontFace> FontFace::create(Document* document, const StyleRuleFontFace* fontFaceRule)
    177 {
    178     const StylePropertySet& properties = fontFaceRule->properties();
    179 
    180     // Obtain the font-family property and the src property. Both must be defined.
    181     RefPtrWillBeRawPtr<CSSValue> family = properties.getPropertyCSSValue(CSSPropertyFontFamily);
    182     if (!family || !family->isValueList())
    183         return nullptr;
    184     RefPtrWillBeRawPtr<CSSValue> src = properties.getPropertyCSSValue(CSSPropertySrc);
    185     if (!src || !src->isValueList())
    186         return nullptr;
    187 
    188     RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace());
    189 
    190     if (fontFace->setFamilyValue(toCSSValueList(family.get()))
    191         && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStyle)
    192         && fontFace->setPropertyFromStyle(properties, CSSPropertyFontWeight)
    193         && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStretch)
    194         && fontFace->setPropertyFromStyle(properties, CSSPropertyUnicodeRange)
    195         && fontFace->setPropertyFromStyle(properties, CSSPropertyFontVariant)
    196         && fontFace->setPropertyFromStyle(properties, CSSPropertyWebkitFontFeatureSettings)
    197         && !fontFace->family().isEmpty()
    198         && fontFace->traits().mask()) {
    199         fontFace->initCSSFontFace(document, src);
    200         return fontFace.release();
    201     }
    202     return nullptr;
    203 }
    204 
    205 FontFace::FontFace()
    206     : m_status(Unloaded)
    207 {
    208 }
    209 
    210 FontFace::~FontFace()
    211 {
    212 }
    213 
    214 String FontFace::style() const
    215 {
    216     return m_style ? m_style->cssText() : "normal";
    217 }
    218 
    219 String FontFace::weight() const
    220 {
    221     return m_weight ? m_weight->cssText() : "normal";
    222 }
    223 
    224 String FontFace::stretch() const
    225 {
    226     return m_stretch ? m_stretch->cssText() : "normal";
    227 }
    228 
    229 String FontFace::unicodeRange() const
    230 {
    231     return m_unicodeRange ? m_unicodeRange->cssText() : "U+0-10FFFF";
    232 }
    233 
    234 String FontFace::variant() const
    235 {
    236     return m_variant ? m_variant->cssText() : "normal";
    237 }
    238 
    239 String FontFace::featureSettings() const
    240 {
    241     return m_featureSettings ? m_featureSettings->cssText() : "normal";
    242 }
    243 
    244 void FontFace::setStyle(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
    245 {
    246     setPropertyFromString(toDocument(context), s, CSSPropertyFontStyle, exceptionState);
    247 }
    248 
    249 void FontFace::setWeight(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
    250 {
    251     setPropertyFromString(toDocument(context), s, CSSPropertyFontWeight, exceptionState);
    252 }
    253 
    254 void FontFace::setStretch(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
    255 {
    256     setPropertyFromString(toDocument(context), s, CSSPropertyFontStretch, exceptionState);
    257 }
    258 
    259 void FontFace::setUnicodeRange(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
    260 {
    261     setPropertyFromString(toDocument(context), s, CSSPropertyUnicodeRange, exceptionState);
    262 }
    263 
    264 void FontFace::setVariant(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
    265 {
    266     setPropertyFromString(toDocument(context), s, CSSPropertyFontVariant, exceptionState);
    267 }
    268 
    269 void FontFace::setFeatureSettings(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
    270 {
    271     setPropertyFromString(toDocument(context), s, CSSPropertyWebkitFontFeatureSettings, exceptionState);
    272 }
    273 
    274 void FontFace::setPropertyFromString(const Document* document, const String& s, CSSPropertyID propertyID, ExceptionState& exceptionState)
    275 {
    276     RefPtrWillBeRawPtr<CSSValue> value = parseCSSValue(document, s, propertyID);
    277     if (!value || !setPropertyValue(value, propertyID))
    278         exceptionState.throwDOMException(SyntaxError, "Failed to set '" + s + "' as a property value.");
    279 }
    280 
    281 bool FontFace::setPropertyFromStyle(const StylePropertySet& properties, CSSPropertyID propertyID)
    282 {
    283     return setPropertyValue(properties.getPropertyCSSValue(propertyID), propertyID);
    284 }
    285 
    286 bool FontFace::setPropertyValue(PassRefPtrWillBeRawPtr<CSSValue> value, CSSPropertyID propertyID)
    287 {
    288     switch (propertyID) {
    289     case CSSPropertyFontStyle:
    290         m_style = value;
    291         break;
    292     case CSSPropertyFontWeight:
    293         m_weight = value;
    294         break;
    295     case CSSPropertyFontStretch:
    296         m_stretch = value;
    297         break;
    298     case CSSPropertyUnicodeRange:
    299         if (value && !value->isValueList())
    300             return false;
    301         m_unicodeRange = value;
    302         break;
    303     case CSSPropertyFontVariant:
    304         m_variant = value;
    305         break;
    306     case CSSPropertyWebkitFontFeatureSettings:
    307         m_featureSettings = value;
    308         break;
    309     default:
    310         ASSERT_NOT_REACHED();
    311         return false;
    312     }
    313     return true;
    314 }
    315 
    316 bool FontFace::setFamilyValue(CSSValueList* familyList)
    317 {
    318     // The font-family descriptor has to have exactly one family name.
    319     if (familyList->length() != 1)
    320         return false;
    321 
    322     CSSPrimitiveValue* familyValue = toCSSPrimitiveValue(familyList->itemWithoutBoundsCheck(0));
    323     AtomicString family;
    324     if (familyValue->isString()) {
    325         family = AtomicString(familyValue->getStringValue());
    326     } else if (familyValue->isValueID()) {
    327         // We need to use the raw text for all the generic family types, since @font-face is a way of actually
    328         // defining what font to use for those types.
    329         switch (familyValue->getValueID()) {
    330         case CSSValueSerif:
    331             family =  FontFamilyNames::webkit_serif;
    332             break;
    333         case CSSValueSansSerif:
    334             family =  FontFamilyNames::webkit_sans_serif;
    335             break;
    336         case CSSValueCursive:
    337             family =  FontFamilyNames::webkit_cursive;
    338             break;
    339         case CSSValueFantasy:
    340             family =  FontFamilyNames::webkit_fantasy;
    341             break;
    342         case CSSValueMonospace:
    343             family =  FontFamilyNames::webkit_monospace;
    344             break;
    345         case CSSValueWebkitPictograph:
    346             family =  FontFamilyNames::webkit_pictograph;
    347             break;
    348         default:
    349             return false;
    350         }
    351     }
    352     m_family = family;
    353     return true;
    354 }
    355 
    356 String FontFace::status() const
    357 {
    358     switch (m_status) {
    359     case Unloaded:
    360         return "unloaded";
    361     case Loading:
    362         return "loading";
    363     case Loaded:
    364         return "loaded";
    365     case Error:
    366         return "error";
    367     default:
    368         ASSERT_NOT_REACHED();
    369     }
    370     return emptyString();
    371 }
    372 
    373 void FontFace::setLoadStatus(LoadStatus status)
    374 {
    375     m_status = status;
    376     if (m_status == Error)
    377         m_error = DOMError::create(NetworkError);
    378     if (m_status == Loaded || m_status == Error) {
    379         resolveReadyPromises();
    380 
    381         WillBeHeapVector<RefPtrWillBeMember<LoadFontCallback> > callbacks;
    382         m_callbacks.swap(callbacks);
    383         for (size_t i = 0; i < callbacks.size(); ++i) {
    384             if (m_status == Loaded)
    385                 callbacks[i]->notifyLoaded(this);
    386             else
    387                 callbacks[i]->notifyError(this);
    388         }
    389     }
    390 }
    391 
    392 ScriptPromise FontFace::fontStatusPromise(ScriptState* scriptState)
    393 {
    394     // Since we cannot hold a ScriptPromise as a member of FontFace (that will
    395     // cause a circular reference), this creates new Promise every time.
    396     OwnPtr<FontFaceReadyPromiseResolver> resolver = FontFaceReadyPromiseResolver::create(scriptState);
    397     ScriptPromise promise = resolver->promise();
    398     if (m_status == Loaded || m_status == Error)
    399         resolver->resolve(this);
    400     else
    401         m_readyResolvers.append(resolver.release());
    402 
    403     return promise;
    404 }
    405 
    406 ScriptPromise FontFace::load(ScriptState* scriptState)
    407 {
    408     loadInternal(scriptState->executionContext());
    409     return fontStatusPromise(scriptState);
    410 }
    411 
    412 void FontFace::loadWithCallback(PassRefPtrWillBeRawPtr<LoadFontCallback> callback, ExecutionContext* context)
    413 {
    414     loadInternal(context);
    415     if (m_status == Loaded)
    416         callback->notifyLoaded(this);
    417     else if (m_status == Error)
    418         callback->notifyError(this);
    419     else
    420         m_callbacks.append(callback);
    421 }
    422 
    423 void FontFace::loadInternal(ExecutionContext* context)
    424 {
    425     if (m_status != Unloaded)
    426         return;
    427 
    428     m_cssFontFace->load();
    429     toDocument(context)->styleEngine()->fontSelector()->fontLoader()->loadPendingFonts();
    430 }
    431 
    432 void FontFace::resolveReadyPromises()
    433 {
    434     for (size_t i = 0; i < m_readyResolvers.size(); i++)
    435         m_readyResolvers[i]->resolve(this);
    436     m_readyResolvers.clear();
    437 }
    438 
    439 FontTraits FontFace::traits() const
    440 {
    441     FontStyle style = FontStyleNormal;
    442     if (m_style) {
    443         if (!m_style->isPrimitiveValue())
    444             return 0;
    445 
    446         switch (toCSSPrimitiveValue(m_style.get())->getValueID()) {
    447         case CSSValueNormal:
    448             style = FontStyleNormal;
    449             break;
    450         case CSSValueItalic:
    451         case CSSValueOblique:
    452             style = FontStyleItalic;
    453             break;
    454         default:
    455             break;
    456         }
    457     }
    458 
    459     FontWeight weight = FontWeight400;
    460     if (m_weight) {
    461         if (!m_weight->isPrimitiveValue())
    462             return 0;
    463 
    464         switch (toCSSPrimitiveValue(m_weight.get())->getValueID()) {
    465         case CSSValueBold:
    466         case CSSValue700:
    467             weight = FontWeight700;
    468             break;
    469         case CSSValueNormal:
    470         case CSSValue400:
    471             weight = FontWeight400;
    472             break;
    473         case CSSValue900:
    474             weight = FontWeight900;
    475             break;
    476         case CSSValue800:
    477             weight = FontWeight800;
    478             break;
    479         case CSSValue600:
    480             weight = FontWeight600;
    481             break;
    482         case CSSValue500:
    483             weight = FontWeight500;
    484             break;
    485         case CSSValue300:
    486             weight = FontWeight300;
    487             break;
    488         case CSSValue200:
    489             weight = FontWeight200;
    490             break;
    491         case CSSValueLighter:
    492         case CSSValue100:
    493             weight = FontWeight100;
    494             break;
    495         default:
    496             ASSERT_NOT_REACHED();
    497             break;
    498         }
    499     }
    500 
    501     FontVariant variant = FontVariantNormal;
    502     if (RefPtrWillBeRawPtr<CSSValue> fontVariant = m_variant) {
    503         // font-variant descriptor can be a value list.
    504         if (fontVariant->isPrimitiveValue()) {
    505             RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
    506             list->append(fontVariant);
    507             fontVariant = list;
    508         } else if (!fontVariant->isValueList()) {
    509             return 0;
    510         }
    511 
    512         CSSValueList* variantList = toCSSValueList(fontVariant.get());
    513         unsigned numVariants = variantList->length();
    514         if (!numVariants)
    515             return 0;
    516 
    517         for (unsigned i = 0; i < numVariants; ++i) {
    518             switch (toCSSPrimitiveValue(variantList->itemWithoutBoundsCheck(i))->getValueID()) {
    519             case CSSValueNormal:
    520                 variant = FontVariantNormal;
    521                 break;
    522             case CSSValueSmallCaps:
    523                 variant = FontVariantSmallCaps;
    524                 break;
    525             default:
    526                 break;
    527             }
    528         }
    529     }
    530 
    531     return FontTraits(style, variant, weight, FontStretchNormal);
    532 }
    533 
    534 static PassOwnPtrWillBeRawPtr<CSSFontFace> createCSSFontFace(FontFace* fontFace, CSSValue* unicodeRange)
    535 {
    536     Vector<CSSFontFace::UnicodeRange> ranges;
    537     if (CSSValueList* rangeList = toCSSValueList(unicodeRange)) {
    538         unsigned numRanges = rangeList->length();
    539         for (unsigned i = 0; i < numRanges; i++) {
    540             CSSUnicodeRangeValue* range = toCSSUnicodeRangeValue(rangeList->itemWithoutBoundsCheck(i));
    541             ranges.append(CSSFontFace::UnicodeRange(range->from(), range->to()));
    542         }
    543     }
    544 
    545     return adoptPtrWillBeNoop(new CSSFontFace(fontFace, ranges));
    546 }
    547 
    548 void FontFace::initCSSFontFace(Document* document, PassRefPtrWillBeRawPtr<CSSValue> src)
    549 {
    550     m_cssFontFace = createCSSFontFace(this, m_unicodeRange.get());
    551 
    552     // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace.
    553     CSSValueList* srcList = toCSSValueList(src.get());
    554     int srcLength = srcList->length();
    555 
    556     bool foundSVGFont = false;
    557 
    558     for (int i = 0; i < srcLength; i++) {
    559         // An item in the list either specifies a string (local font name) or a URL (remote font to download).
    560         CSSFontFaceSrcValue* item = toCSSFontFaceSrcValue(srcList->itemWithoutBoundsCheck(i));
    561         OwnPtrWillBeRawPtr<CSSFontFaceSource> source = nullptr;
    562 
    563 #if ENABLE(SVG_FONTS)
    564         foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement();
    565 #endif
    566         if (!item->isLocal()) {
    567             Settings* settings = document ? document->frame() ? document->frame()->settings() : 0 : 0;
    568             bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled());
    569             if (allowDownloading && item->isSupportedFormat() && document) {
    570                 FontResource* fetched = item->fetch(document);
    571                 if (fetched) {
    572                     FontLoader* fontLoader = document->styleEngine()->fontSelector()->fontLoader();
    573 
    574 #if ENABLE(SVG_FONTS)
    575                     if (foundSVGFont) {
    576                         source = adoptPtrWillBeNoop(new SVGRemoteFontFaceSource(item->resource(), fetched, fontLoader));
    577                     } else
    578 #endif
    579                     {
    580                         source = adoptPtrWillBeNoop(new RemoteFontFaceSource(fetched, fontLoader));
    581                     }
    582                 }
    583             }
    584         } else {
    585 #if ENABLE(SVG_FONTS)
    586             if (item->svgFontFaceElement()) {
    587                 RefPtrWillBeRawPtr<SVGFontFaceElement> fontfaceElement = item->svgFontFaceElement();
    588                 // SVGFontFaceSource assumes that it is the case where <font-face> element resides in the same document.
    589                 // We put a RELEASE_ASSERT here as it will cause UAF if the assumption is false.
    590                 RELEASE_ASSERT(fontfaceElement->inDocument());
    591                 RELEASE_ASSERT(fontfaceElement->document() == document);
    592                 source = adoptPtrWillBeNoop(new SVGFontFaceSource(fontfaceElement.get()));
    593             } else
    594 #endif
    595             {
    596                 source = adoptPtrWillBeNoop(new LocalFontFaceSource(item->resource()));
    597             }
    598         }
    599 
    600         if (source)
    601             m_cssFontFace->addSource(source.release());
    602     }
    603 }
    604 
    605 void FontFace::initCSSFontFace(const unsigned char* data, unsigned size)
    606 {
    607     m_cssFontFace = createCSSFontFace(this, m_unicodeRange.get());
    608 
    609     RefPtr<SharedBuffer> buffer = SharedBuffer::create(data, size);
    610     OwnPtrWillBeRawPtr<BinaryDataFontFaceSource> source = adoptPtrWillBeNoop(new BinaryDataFontFaceSource(buffer.get()));
    611     if (source->isValid()) {
    612         m_status = Loaded;
    613     } else {
    614         m_status = Error;
    615         m_error = DOMError::create(SyntaxError, "Invalid font data in ArrayBuffer.");
    616     }
    617     m_cssFontFace->addSource(source.release());
    618 }
    619 
    620 void FontFace::trace(Visitor* visitor)
    621 {
    622     visitor->trace(m_src);
    623     visitor->trace(m_style);
    624     visitor->trace(m_weight);
    625     visitor->trace(m_stretch);
    626     visitor->trace(m_unicodeRange);
    627     visitor->trace(m_variant);
    628     visitor->trace(m_featureSettings);
    629     visitor->trace(m_error);
    630     visitor->trace(m_cssFontFace);
    631     visitor->trace(m_callbacks);
    632 }
    633 
    634 bool FontFace::hadBlankText() const
    635 {
    636     return m_cssFontFace->hadBlankText();
    637 }
    638 
    639 } // namespace WebCore
    640