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/core/v8/ExceptionState.h"
35 #include "bindings/core/v8/ScriptState.h"
36 #include "core/CSSValueKeywords.h"
37 #include "core/css/BinaryDataFontFaceSource.h"
38 #include "core/css/CSSFontFace.h"
39 #include "core/css/CSSFontFaceSrcValue.h"
40 #include "core/css/CSSFontSelector.h"
41 #include "core/css/CSSPrimitiveValue.h"
42 #include "core/css/CSSUnicodeRangeValue.h"
43 #include "core/css/CSSValueList.h"
44 #include "core/css/FontFaceDescriptors.h"
45 #include "core/css/LocalFontFaceSource.h"
46 #include "core/css/RemoteFontFaceSource.h"
47 #include "core/css/StylePropertySet.h"
48 #include "core/css/StyleRule.h"
49 #include "core/css/parser/CSSParser.h"
50 #include "core/dom/DOMException.h"
51 #include "core/dom/Document.h"
52 #include "core/dom/ExceptionCode.h"
53 #include "core/dom/StyleEngine.h"
54 #include "core/frame/LocalFrame.h"
55 #include "core/frame/Settings.h"
56 #include "core/frame/UseCounter.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 blink {
64
parseCSSValue(const Document * document,const String & s,CSSPropertyID propertyID)65 static PassRefPtrWillBeRawPtr<CSSValue> parseCSSValue(const Document* document, const String& s, CSSPropertyID propertyID)
66 {
67 CSSParserContext context(*document, UseCounter::getFrom(document));
68 return CSSParser::parseSingleValue(propertyID, s, context);
69 }
70
create(ExecutionContext * context,const AtomicString & family,const String & source,const FontFaceDescriptors & descriptors)71 PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, const String& source, const FontFaceDescriptors& descriptors)
72 {
73 RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace(context, family, descriptors));
74
75 RefPtrWillBeRawPtr<CSSValue> src = parseCSSValue(toDocument(context), source, CSSPropertySrc);
76 if (!src || !src->isValueList())
77 fontFace->setError(DOMException::create(SyntaxError, "The source provided ('" + source + "') could not be parsed as a value list."));
78
79 fontFace->initCSSFontFace(toDocument(context), src);
80 return fontFace.release();
81 }
82
create(ExecutionContext * context,const AtomicString & family,PassRefPtr<ArrayBuffer> source,const FontFaceDescriptors & descriptors)83 PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, PassRefPtr<ArrayBuffer> source, const FontFaceDescriptors& descriptors)
84 {
85 RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace(context, family, descriptors));
86 fontFace->initCSSFontFace(static_cast<const unsigned char*>(source->data()), source->byteLength());
87 return fontFace.release();
88 }
89
create(ExecutionContext * context,const AtomicString & family,PassRefPtr<ArrayBufferView> source,const FontFaceDescriptors & descriptors)90 PassRefPtrWillBeRawPtr<FontFace> FontFace::create(ExecutionContext* context, const AtomicString& family, PassRefPtr<ArrayBufferView> source, const FontFaceDescriptors& descriptors)
91 {
92 RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace(context, family, descriptors));
93 fontFace->initCSSFontFace(static_cast<const unsigned char*>(source->baseAddress()), source->byteLength());
94 return fontFace.release();
95 }
96
create(Document * document,const StyleRuleFontFace * fontFaceRule)97 PassRefPtrWillBeRawPtr<FontFace> FontFace::create(Document* document, const StyleRuleFontFace* fontFaceRule)
98 {
99 const StylePropertySet& properties = fontFaceRule->properties();
100
101 // Obtain the font-family property and the src property. Both must be defined.
102 RefPtrWillBeRawPtr<CSSValue> family = properties.getPropertyCSSValue(CSSPropertyFontFamily);
103 if (!family || !family->isValueList())
104 return nullptr;
105 RefPtrWillBeRawPtr<CSSValue> src = properties.getPropertyCSSValue(CSSPropertySrc);
106 if (!src || !src->isValueList())
107 return nullptr;
108
109 RefPtrWillBeRawPtr<FontFace> fontFace = adoptRefWillBeNoop(new FontFace(document));
110
111 if (fontFace->setFamilyValue(toCSSValueList(family.get()))
112 && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStyle)
113 && fontFace->setPropertyFromStyle(properties, CSSPropertyFontWeight)
114 && fontFace->setPropertyFromStyle(properties, CSSPropertyFontStretch)
115 && fontFace->setPropertyFromStyle(properties, CSSPropertyUnicodeRange)
116 && fontFace->setPropertyFromStyle(properties, CSSPropertyFontVariant)
117 && fontFace->setPropertyFromStyle(properties, CSSPropertyWebkitFontFeatureSettings)
118 && !fontFace->family().isEmpty()
119 && fontFace->traits().bitfield()) {
120 fontFace->initCSSFontFace(document, src);
121 return fontFace.release();
122 }
123 return nullptr;
124 }
125
FontFace(ExecutionContext * context)126 FontFace::FontFace(ExecutionContext* context)
127 : ActiveDOMObject(context)
128 , m_status(Unloaded)
129 {
130 suspendIfNeeded();
131 }
132
FontFace(ExecutionContext * context,const AtomicString & family,const FontFaceDescriptors & descriptors)133 FontFace::FontFace(ExecutionContext* context, const AtomicString& family, const FontFaceDescriptors& descriptors)
134 : ActiveDOMObject(context)
135 , m_family(family)
136 , m_status(Unloaded)
137 {
138 Document* document = toDocument(context);
139 setPropertyFromString(document, descriptors.style(), CSSPropertyFontStyle);
140 setPropertyFromString(document, descriptors.weight(), CSSPropertyFontWeight);
141 // FIXME: we don't implement 'font-strech' property yet so we can't set the property.
142 setPropertyFromString(document, descriptors.unicodeRange(), CSSPropertyUnicodeRange);
143 setPropertyFromString(document, descriptors.variant(), CSSPropertyFontVariant);
144 setPropertyFromString(document, descriptors.featureSettings(), CSSPropertyWebkitFontFeatureSettings);
145
146 suspendIfNeeded();
147 }
148
~FontFace()149 FontFace::~FontFace()
150 {
151 }
152
style() const153 String FontFace::style() const
154 {
155 return m_style ? m_style->cssText() : "normal";
156 }
157
weight() const158 String FontFace::weight() const
159 {
160 return m_weight ? m_weight->cssText() : "normal";
161 }
162
stretch() const163 String FontFace::stretch() const
164 {
165 return m_stretch ? m_stretch->cssText() : "normal";
166 }
167
unicodeRange() const168 String FontFace::unicodeRange() const
169 {
170 return m_unicodeRange ? m_unicodeRange->cssText() : "U+0-10FFFF";
171 }
172
variant() const173 String FontFace::variant() const
174 {
175 return m_variant ? m_variant->cssText() : "normal";
176 }
177
featureSettings() const178 String FontFace::featureSettings() const
179 {
180 return m_featureSettings ? m_featureSettings->cssText() : "normal";
181 }
182
setStyle(ExecutionContext * context,const String & s,ExceptionState & exceptionState)183 void FontFace::setStyle(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
184 {
185 setPropertyFromString(toDocument(context), s, CSSPropertyFontStyle, &exceptionState);
186 }
187
setWeight(ExecutionContext * context,const String & s,ExceptionState & exceptionState)188 void FontFace::setWeight(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
189 {
190 setPropertyFromString(toDocument(context), s, CSSPropertyFontWeight, &exceptionState);
191 }
192
setStretch(ExecutionContext * context,const String & s,ExceptionState & exceptionState)193 void FontFace::setStretch(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
194 {
195 setPropertyFromString(toDocument(context), s, CSSPropertyFontStretch, &exceptionState);
196 }
197
setUnicodeRange(ExecutionContext * context,const String & s,ExceptionState & exceptionState)198 void FontFace::setUnicodeRange(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
199 {
200 setPropertyFromString(toDocument(context), s, CSSPropertyUnicodeRange, &exceptionState);
201 }
202
setVariant(ExecutionContext * context,const String & s,ExceptionState & exceptionState)203 void FontFace::setVariant(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
204 {
205 setPropertyFromString(toDocument(context), s, CSSPropertyFontVariant, &exceptionState);
206 }
207
setFeatureSettings(ExecutionContext * context,const String & s,ExceptionState & exceptionState)208 void FontFace::setFeatureSettings(ExecutionContext* context, const String& s, ExceptionState& exceptionState)
209 {
210 setPropertyFromString(toDocument(context), s, CSSPropertyWebkitFontFeatureSettings, &exceptionState);
211 }
212
setPropertyFromString(const Document * document,const String & s,CSSPropertyID propertyID,ExceptionState * exceptionState)213 void FontFace::setPropertyFromString(const Document* document, const String& s, CSSPropertyID propertyID, ExceptionState* exceptionState)
214 {
215 RefPtrWillBeRawPtr<CSSValue> value = parseCSSValue(document, s, propertyID);
216 if (value && setPropertyValue(value, propertyID))
217 return;
218
219 String message = "Failed to set '" + s + "' as a property value.";
220 if (exceptionState)
221 exceptionState->throwDOMException(SyntaxError, message);
222 else
223 setError(DOMException::create(SyntaxError, message));
224 }
225
setPropertyFromStyle(const StylePropertySet & properties,CSSPropertyID propertyID)226 bool FontFace::setPropertyFromStyle(const StylePropertySet& properties, CSSPropertyID propertyID)
227 {
228 return setPropertyValue(properties.getPropertyCSSValue(propertyID), propertyID);
229 }
230
setPropertyValue(PassRefPtrWillBeRawPtr<CSSValue> value,CSSPropertyID propertyID)231 bool FontFace::setPropertyValue(PassRefPtrWillBeRawPtr<CSSValue> value, CSSPropertyID propertyID)
232 {
233 switch (propertyID) {
234 case CSSPropertyFontStyle:
235 m_style = value;
236 break;
237 case CSSPropertyFontWeight:
238 m_weight = value;
239 break;
240 case CSSPropertyFontStretch:
241 m_stretch = value;
242 break;
243 case CSSPropertyUnicodeRange:
244 if (value && !value->isValueList())
245 return false;
246 m_unicodeRange = value;
247 break;
248 case CSSPropertyFontVariant:
249 m_variant = value;
250 break;
251 case CSSPropertyWebkitFontFeatureSettings:
252 m_featureSettings = value;
253 break;
254 default:
255 ASSERT_NOT_REACHED();
256 return false;
257 }
258 return true;
259 }
260
setFamilyValue(CSSValueList * familyList)261 bool FontFace::setFamilyValue(CSSValueList* familyList)
262 {
263 // The font-family descriptor has to have exactly one family name.
264 if (familyList->length() != 1)
265 return false;
266
267 CSSPrimitiveValue* familyValue = toCSSPrimitiveValue(familyList->item(0));
268 AtomicString family;
269 if (familyValue->isString()) {
270 family = AtomicString(familyValue->getStringValue());
271 } else if (familyValue->isValueID()) {
272 // We need to use the raw text for all the generic family types, since @font-face is a way of actually
273 // defining what font to use for those types.
274 switch (familyValue->getValueID()) {
275 case CSSValueSerif:
276 family = FontFamilyNames::webkit_serif;
277 break;
278 case CSSValueSansSerif:
279 family = FontFamilyNames::webkit_sans_serif;
280 break;
281 case CSSValueCursive:
282 family = FontFamilyNames::webkit_cursive;
283 break;
284 case CSSValueFantasy:
285 family = FontFamilyNames::webkit_fantasy;
286 break;
287 case CSSValueMonospace:
288 family = FontFamilyNames::webkit_monospace;
289 break;
290 case CSSValueWebkitPictograph:
291 family = FontFamilyNames::webkit_pictograph;
292 break;
293 default:
294 return false;
295 }
296 }
297 m_family = family;
298 return true;
299 }
300
status() const301 String FontFace::status() const
302 {
303 switch (m_status) {
304 case Unloaded:
305 return "unloaded";
306 case Loading:
307 return "loading";
308 case Loaded:
309 return "loaded";
310 case Error:
311 return "error";
312 default:
313 ASSERT_NOT_REACHED();
314 }
315 return emptyString();
316 }
317
setLoadStatus(LoadStatus status)318 void FontFace::setLoadStatus(LoadStatus status)
319 {
320 m_status = status;
321 ASSERT(m_status != Error || m_error);
322
323 if (m_status == Loaded || m_status == Error) {
324 if (m_loadedProperty) {
325 if (m_status == Loaded)
326 m_loadedProperty->resolve(this);
327 else
328 m_loadedProperty->reject(m_error.get());
329 }
330
331 WillBeHeapVector<RefPtrWillBeMember<LoadFontCallback> > callbacks;
332 m_callbacks.swap(callbacks);
333 for (size_t i = 0; i < callbacks.size(); ++i) {
334 if (m_status == Loaded)
335 callbacks[i]->notifyLoaded(this);
336 else
337 callbacks[i]->notifyError(this);
338 }
339 }
340 }
341
setError(PassRefPtrWillBeRawPtr<DOMException> error)342 void FontFace::setError(PassRefPtrWillBeRawPtr<DOMException> error)
343 {
344 if (!m_error)
345 m_error = error ? error : DOMException::create(NetworkError);
346 setLoadStatus(Error);
347 }
348
fontStatusPromise(ScriptState * scriptState)349 ScriptPromise FontFace::fontStatusPromise(ScriptState* scriptState)
350 {
351 if (!m_loadedProperty) {
352 m_loadedProperty = new LoadedProperty(scriptState->executionContext(), this, LoadedProperty::Loaded);
353 if (m_status == Loaded)
354 m_loadedProperty->resolve(this);
355 else if (m_status == Error)
356 m_loadedProperty->reject(m_error.get());
357 }
358 return m_loadedProperty->promise(scriptState->world());
359 }
360
load(ScriptState * scriptState)361 ScriptPromise FontFace::load(ScriptState* scriptState)
362 {
363 loadInternal(scriptState->executionContext());
364 return fontStatusPromise(scriptState);
365 }
366
loadWithCallback(PassRefPtrWillBeRawPtr<LoadFontCallback> callback,ExecutionContext * context)367 void FontFace::loadWithCallback(PassRefPtrWillBeRawPtr<LoadFontCallback> callback, ExecutionContext* context)
368 {
369 loadInternal(context);
370 if (m_status == Loaded)
371 callback->notifyLoaded(this);
372 else if (m_status == Error)
373 callback->notifyError(this);
374 else
375 m_callbacks.append(callback);
376 }
377
loadInternal(ExecutionContext * context)378 void FontFace::loadInternal(ExecutionContext* context)
379 {
380 if (m_status != Unloaded)
381 return;
382
383 m_cssFontFace->load();
384 toDocument(context)->styleEngine()->fontSelector()->fontLoader()->loadPendingFonts();
385 }
386
traits() const387 FontTraits FontFace::traits() const
388 {
389 FontStyle style = FontStyleNormal;
390 if (m_style) {
391 if (!m_style->isPrimitiveValue())
392 return 0;
393
394 switch (toCSSPrimitiveValue(m_style.get())->getValueID()) {
395 case CSSValueNormal:
396 style = FontStyleNormal;
397 break;
398 case CSSValueItalic:
399 case CSSValueOblique:
400 style = FontStyleItalic;
401 break;
402 default:
403 break;
404 }
405 }
406
407 FontWeight weight = FontWeight400;
408 if (m_weight) {
409 if (!m_weight->isPrimitiveValue())
410 return 0;
411
412 switch (toCSSPrimitiveValue(m_weight.get())->getValueID()) {
413 case CSSValueBold:
414 case CSSValue700:
415 weight = FontWeight700;
416 break;
417 case CSSValueNormal:
418 case CSSValue400:
419 weight = FontWeight400;
420 break;
421 case CSSValue900:
422 weight = FontWeight900;
423 break;
424 case CSSValue800:
425 weight = FontWeight800;
426 break;
427 case CSSValue600:
428 weight = FontWeight600;
429 break;
430 case CSSValue500:
431 weight = FontWeight500;
432 break;
433 case CSSValue300:
434 weight = FontWeight300;
435 break;
436 case CSSValue200:
437 weight = FontWeight200;
438 break;
439 case CSSValue100:
440 weight = FontWeight100;
441 break;
442 // Although 'lighter' and 'bolder' are valid keywords for font-weights, they are invalid
443 // inside font-face rules so they are ignored. Reference: http://www.w3.org/TR/css3-fonts/#descdef-font-weight.
444 case CSSValueLighter:
445 case CSSValueBolder:
446 break;
447 default:
448 ASSERT_NOT_REACHED();
449 break;
450 }
451 }
452
453 FontVariant variant = FontVariantNormal;
454 if (RefPtrWillBeRawPtr<CSSValue> fontVariant = m_variant) {
455 // font-variant descriptor can be a value list.
456 if (fontVariant->isPrimitiveValue()) {
457 RefPtrWillBeRawPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
458 list->append(fontVariant);
459 fontVariant = list;
460 } else if (!fontVariant->isValueList()) {
461 return 0;
462 }
463
464 CSSValueList* variantList = toCSSValueList(fontVariant.get());
465 unsigned numVariants = variantList->length();
466 if (!numVariants)
467 return 0;
468
469 for (unsigned i = 0; i < numVariants; ++i) {
470 switch (toCSSPrimitiveValue(variantList->item(i))->getValueID()) {
471 case CSSValueNormal:
472 variant = FontVariantNormal;
473 break;
474 case CSSValueSmallCaps:
475 variant = FontVariantSmallCaps;
476 break;
477 default:
478 break;
479 }
480 }
481 }
482
483 return FontTraits(style, variant, weight, FontStretchNormal);
484 }
485
createCSSFontFace(FontFace * fontFace,CSSValue * unicodeRange)486 static PassOwnPtrWillBeRawPtr<CSSFontFace> createCSSFontFace(FontFace* fontFace, CSSValue* unicodeRange)
487 {
488 Vector<CSSFontFace::UnicodeRange> ranges;
489 if (CSSValueList* rangeList = toCSSValueList(unicodeRange)) {
490 unsigned numRanges = rangeList->length();
491 for (unsigned i = 0; i < numRanges; i++) {
492 CSSUnicodeRangeValue* range = toCSSUnicodeRangeValue(rangeList->item(i));
493 ranges.append(CSSFontFace::UnicodeRange(range->from(), range->to()));
494 }
495 }
496
497 return adoptPtrWillBeNoop(new CSSFontFace(fontFace, ranges));
498 }
499
initCSSFontFace(Document * document,PassRefPtrWillBeRawPtr<CSSValue> src)500 void FontFace::initCSSFontFace(Document* document, PassRefPtrWillBeRawPtr<CSSValue> src)
501 {
502 m_cssFontFace = createCSSFontFace(this, m_unicodeRange.get());
503 if (m_error)
504 return;
505
506 // Each item in the src property's list is a single CSSFontFaceSource. Put them all into a CSSFontFace.
507 ASSERT(src);
508 ASSERT(src->isValueList());
509 CSSValueList* srcList = toCSSValueList(src.get());
510 int srcLength = srcList->length();
511
512 bool foundSVGFont = false;
513
514 for (int i = 0; i < srcLength; i++) {
515 // An item in the list either specifies a string (local font name) or a URL (remote font to download).
516 CSSFontFaceSrcValue* item = toCSSFontFaceSrcValue(srcList->item(i));
517 OwnPtrWillBeRawPtr<CSSFontFaceSource> source = nullptr;
518
519 #if ENABLE(SVG_FONTS)
520 foundSVGFont = item->isSVGFontFaceSrc() || item->svgFontFaceElement();
521 #endif
522 if (!item->isLocal()) {
523 Settings* settings = document ? document->frame() ? document->frame()->settings() : 0 : 0;
524 bool allowDownloading = foundSVGFont || (settings && settings->downloadableBinaryFontsEnabled());
525 if (allowDownloading && item->isSupportedFormat() && document) {
526 FontResource* fetched = item->fetch(document);
527 if (fetched) {
528 FontLoader* fontLoader = document->styleEngine()->fontSelector()->fontLoader();
529
530 #if ENABLE(SVG_FONTS)
531 if (foundSVGFont) {
532 source = adoptPtrWillBeNoop(new SVGRemoteFontFaceSource(item->resource(), fetched, fontLoader));
533 } else
534 #endif
535 {
536 source = adoptPtrWillBeNoop(new RemoteFontFaceSource(fetched, fontLoader));
537 }
538 }
539 }
540 } else {
541 #if ENABLE(SVG_FONTS)
542 if (item->svgFontFaceElement()) {
543 RefPtrWillBeRawPtr<SVGFontFaceElement> fontfaceElement = item->svgFontFaceElement();
544 // SVGFontFaceSource assumes that it is the case where <font-face> element resides in the same document.
545 // We put a RELEASE_ASSERT here as it will cause UAF if the assumption is false.
546 RELEASE_ASSERT(fontfaceElement->inDocument());
547 RELEASE_ASSERT(fontfaceElement->document() == document);
548 source = adoptPtrWillBeNoop(new SVGFontFaceSource(fontfaceElement.get()));
549 } else
550 #endif
551 {
552 source = adoptPtrWillBeNoop(new LocalFontFaceSource(item->resource()));
553 }
554 }
555
556 if (source)
557 m_cssFontFace->addSource(source.release());
558 }
559 }
560
initCSSFontFace(const unsigned char * data,unsigned size)561 void FontFace::initCSSFontFace(const unsigned char* data, unsigned size)
562 {
563 m_cssFontFace = createCSSFontFace(this, m_unicodeRange.get());
564 if (m_error)
565 return;
566
567 RefPtr<SharedBuffer> buffer = SharedBuffer::create(data, size);
568 OwnPtrWillBeRawPtr<BinaryDataFontFaceSource> source = adoptPtrWillBeNoop(new BinaryDataFontFaceSource(buffer.get()));
569 if (source->isValid())
570 setLoadStatus(Loaded);
571 else
572 setError(DOMException::create(SyntaxError, "Invalid font data in ArrayBuffer."));
573 m_cssFontFace->addSource(source.release());
574 }
575
trace(Visitor * visitor)576 void FontFace::trace(Visitor* visitor)
577 {
578 visitor->trace(m_src);
579 visitor->trace(m_style);
580 visitor->trace(m_weight);
581 visitor->trace(m_stretch);
582 visitor->trace(m_unicodeRange);
583 visitor->trace(m_variant);
584 visitor->trace(m_featureSettings);
585 visitor->trace(m_error);
586 visitor->trace(m_loadedProperty);
587 visitor->trace(m_cssFontFace);
588 visitor->trace(m_callbacks);
589 }
590
hadBlankText() const591 bool FontFace::hadBlankText() const
592 {
593 return m_cssFontFace->hadBlankText();
594 }
595
hasPendingActivity() const596 bool FontFace::hasPendingActivity() const
597 {
598 return m_status == Loading && executionContext() && !executionContext()->activeDOMObjectsAreStopped();
599 }
600
601 } // namespace blink
602