blob: e1b1af20fb11ae3dfee192cac92e62cdea557dc8 [file] [log] [blame]
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +00001/*
mmaxfield@apple.com7c336912016-02-18 07:25:56 +00002 * Copyright (C) 2016 Apple Inc. All rights reserved.
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +00003 *
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 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 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 "FontFace.h"
28
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +000029#include "CSSComputedStyleDeclaration.h"
mmaxfield@apple.comc24c78e2016-05-14 19:18:34 +000030#include "CSSFontFaceSource.h"
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +000031#include "CSSFontFeatureValue.h"
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +000032#include "CSSFontStyleValue.h"
achristensen@apple.com2e6f6d62016-05-16 23:11:08 +000033#include "CSSParser.h"
mmaxfield@apple.com0d8cd0b2017-10-06 01:25:01 +000034#include "CSSPrimitiveValueMappings.h"
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +000035#include "CSSUnicodeRangeValue.h"
hyatt@apple.com1f589652016-12-10 18:31:13 +000036#include "CSSValueList.h"
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +000037#include "CSSValuePool.h"
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +000038#include "Document.h"
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +000039#include "FontVariantBuilder.h"
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +000040#include "JSFontFace.h"
rniwa@webkit.org02e8c082019-07-25 21:18:04 +000041#include "Quirks.h"
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +000042#include "StyleProperties.h"
don.olmstead@sony.com71f34a02018-02-07 05:20:34 +000043#include <JavaScriptCore/ArrayBuffer.h>
44#include <JavaScriptCore/ArrayBufferView.h>
45#include <JavaScriptCore/JSCInlines.h>
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +000046#include <wtf/text/StringBuilder.h>
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +000047
48namespace WebCore {
49
mmaxfield@apple.comc24c78e2016-05-14 19:18:34 +000050static bool populateFontFaceWithArrayBuffer(CSSFontFace& fontFace, Ref<JSC::ArrayBufferView>&& arrayBufferView)
51{
ysuzuki@apple.com1d8e24d2019-08-19 06:59:40 +000052 auto source = makeUnique<CSSFontFaceSource>(fontFace, String(), nullptr, nullptr, WTFMove(arrayBufferView));
mmaxfield@apple.comc24c78e2016-05-14 19:18:34 +000053 fontFace.adoptSource(WTFMove(source));
54 return false;
55}
56
weinig@apple.com866ae8d2017-02-15 23:38:18 +000057ExceptionOr<Ref<FontFace>> FontFace::create(Document& document, const String& family, Source&& source, const Descriptors& descriptors)
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +000058{
darin@apple.comd6016702016-05-07 21:14:20 +000059 auto result = adoptRef(*new FontFace(document.fontSelector()));
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +000060
mmaxfield@apple.comc24c78e2016-05-14 19:18:34 +000061 bool dataRequiresAsynchronousLoading = true;
62
rniwa@webkit.org02e8c082019-07-25 21:18:04 +000063 auto setFamilyResult = result->setFamily(document, family);
darin@apple.comfa677492016-10-17 00:16:05 +000064 if (setFamilyResult.hasException())
65 return setFamilyResult.releaseException();
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +000066
weinig@apple.com866ae8d2017-02-15 23:38:18 +000067 auto sourceConversionResult = WTF::switchOn(source,
68 [&] (String& string) -> ExceptionOr<void> {
69 auto value = FontFace::parseString(string, CSSPropertySrc);
jiewen_tan@apple.comb0b8c512017-11-02 05:43:02 +000070 if (!is<CSSValueList>(value))
cdumez@apple.com750df372017-07-25 03:59:12 +000071 return Exception { SyntaxError };
weinig@apple.com866ae8d2017-02-15 23:38:18 +000072 CSSFontFace::appendSources(result->backing(), downcast<CSSValueList>(*value), &document, false);
73 return { };
74 },
75 [&] (RefPtr<ArrayBufferView>& arrayBufferView) -> ExceptionOr<void> {
76 dataRequiresAsynchronousLoading = populateFontFaceWithArrayBuffer(result->backing(), arrayBufferView.releaseNonNull());
77 return { };
78 },
79 [&] (RefPtr<ArrayBuffer>& arrayBuffer) -> ExceptionOr<void> {
utatane.tea@gmail.com473448d2017-02-17 06:04:16 +000080 unsigned byteLength = arrayBuffer->byteLength();
81 auto arrayBufferView = JSC::Uint8Array::create(WTFMove(arrayBuffer), 0, byteLength);
yusukesuzuki@slowstart.orga4f027e2018-10-10 18:29:44 +000082 dataRequiresAsynchronousLoading = populateFontFaceWithArrayBuffer(result->backing(), WTFMove(arrayBufferView));
weinig@apple.com866ae8d2017-02-15 23:38:18 +000083 return { };
84 }
85 );
86
87 if (sourceConversionResult.hasException())
88 return sourceConversionResult.releaseException();
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +000089
mmaxfield@apple.combccd4b92016-05-26 17:08:17 +000090 // These ternaries match the default strings inside the FontFaceDescriptors dictionary inside FontFace.idl.
utatane.tea@gmail.com84077632018-06-23 08:39:34 +000091 auto setStyleResult = result->setStyle(descriptors.style.isEmpty() ? "normal"_s : descriptors.style);
darin@apple.comfa677492016-10-17 00:16:05 +000092 if (setStyleResult.hasException())
93 return setStyleResult.releaseException();
utatane.tea@gmail.com84077632018-06-23 08:39:34 +000094 auto setWeightResult = result->setWeight(descriptors.weight.isEmpty() ? "normal"_s : descriptors.weight);
darin@apple.comfa677492016-10-17 00:16:05 +000095 if (setWeightResult.hasException())
96 return setWeightResult.releaseException();
utatane.tea@gmail.com84077632018-06-23 08:39:34 +000097 auto setStretchResult = result->setStretch(descriptors.stretch.isEmpty() ? "normal"_s : descriptors.stretch);
darin@apple.comfa677492016-10-17 00:16:05 +000098 if (setStretchResult.hasException())
99 return setStretchResult.releaseException();
utatane.tea@gmail.com84077632018-06-23 08:39:34 +0000100 auto setUnicodeRangeResult = result->setUnicodeRange(descriptors.unicodeRange.isEmpty() ? "U+0-10FFFF"_s : descriptors.unicodeRange);
darin@apple.comfa677492016-10-17 00:16:05 +0000101 if (setUnicodeRangeResult.hasException())
102 return setUnicodeRangeResult.releaseException();
utatane.tea@gmail.com84077632018-06-23 08:39:34 +0000103 auto setVariantResult = result->setVariant(descriptors.variant.isEmpty() ? "normal"_s : descriptors.variant);
darin@apple.comfa677492016-10-17 00:16:05 +0000104 if (setVariantResult.hasException())
105 return setVariantResult.releaseException();
utatane.tea@gmail.com84077632018-06-23 08:39:34 +0000106 auto setFeatureSettingsResult = result->setFeatureSettings(descriptors.featureSettings.isEmpty() ? "normal"_s : descriptors.featureSettings);
darin@apple.comfa677492016-10-17 00:16:05 +0000107 if (setFeatureSettingsResult.hasException())
108 return setFeatureSettingsResult.releaseException();
utatane.tea@gmail.com84077632018-06-23 08:39:34 +0000109 auto setDisplayResult = result->setDisplay(descriptors.display.isEmpty() ? "auto"_s : descriptors.display);
mmaxfield@apple.com0d8cd0b2017-10-06 01:25:01 +0000110 if (setDisplayResult.hasException())
111 return setDisplayResult.releaseException();
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000112
mmaxfield@apple.comc24c78e2016-05-14 19:18:34 +0000113 if (!dataRequiresAsynchronousLoading) {
114 result->backing().load();
mmaxfield@apple.com0f7710a2017-05-02 18:02:50 +0000115 auto status = result->backing().status();
116 ASSERT_UNUSED(status, status == CSSFontFace::Status::Success || status == CSSFontFace::Status::Failure);
mmaxfield@apple.comc24c78e2016-05-14 19:18:34 +0000117 }
118
mcatanzaro@igalia.coma7ade272019-03-19 20:04:34 +0000119 return result;
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000120}
121
youenn.fablet@crf.canon.fr6bc37942016-05-07 20:04:27 +0000122Ref<FontFace> FontFace::create(CSSFontFace& face)
mmaxfield@apple.com2b428902016-02-22 21:40:02 +0000123{
youenn.fablet@crf.canon.fr6bc37942016-05-07 20:04:27 +0000124 return adoptRef(*new FontFace(face));
mmaxfield@apple.com2b428902016-02-22 21:40:02 +0000125}
126
youenn.fablet@crf.canon.fr6bc37942016-05-07 20:04:27 +0000127FontFace::FontFace(CSSFontSelector& fontSelector)
zalan@apple.com68fc1e22017-09-23 04:38:45 +0000128 : m_backing(CSSFontFace::create(&fontSelector, nullptr, this))
weinig@apple.com5a46ef02017-08-09 01:01:44 +0000129 , m_loadedPromise(*this, &FontFace::loadedPromiseResolve)
mmaxfield@apple.com2b428902016-02-22 21:40:02 +0000130{
darin@apple.com75ceafc2016-05-07 22:29:01 +0000131 m_backing->addClient(*this);
mmaxfield@apple.com2b428902016-02-22 21:40:02 +0000132}
133
youenn.fablet@crf.canon.fr6bc37942016-05-07 20:04:27 +0000134FontFace::FontFace(CSSFontFace& face)
zalan@apple.com68fc1e22017-09-23 04:38:45 +0000135 : m_backing(face)
weinig@apple.com5a46ef02017-08-09 01:01:44 +0000136 , m_loadedPromise(*this, &FontFace::loadedPromiseResolve)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000137{
mmaxfield@apple.com7c336912016-02-18 07:25:56 +0000138 m_backing->addClient(*this);
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000139}
140
141FontFace::~FontFace()
142{
mmaxfield@apple.com7c336912016-02-18 07:25:56 +0000143 m_backing->removeClient(*this);
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000144}
145
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000146RefPtr<CSSValue> FontFace::parseString(const String& string, CSSPropertyID propertyID)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000147{
hyatt@apple.com1f589652016-12-10 18:31:13 +0000148 // FIXME: Should use the Document to get the right parsing mode.
149 return CSSParser::parseFontFaceDescriptor(propertyID, string, HTMLStandardMode);
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000150}
151
rniwa@webkit.org02e8c082019-07-25 21:18:04 +0000152ExceptionOr<void> FontFace::setFamily(Document& document, const String& family)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000153{
darin@apple.comfa677492016-10-17 00:16:05 +0000154 if (family.isEmpty())
cdumez@apple.com750df372017-07-25 03:59:12 +0000155 return Exception { SyntaxError };
mmaxfield@apple.combccd4b92016-05-26 17:08:17 +0000156
rniwa@webkit.org02e8c082019-07-25 21:18:04 +0000157 String familyNameToUse = family;
158 if (familyNameToUse.contains('\'') && document.quirks().shouldStripQuotationMarkInFontFaceSetFamily())
159 familyNameToUse = family.removeCharacters([](auto character) { return character == '\''; });
160
mmaxfield@apple.com1fa89ac2019-03-29 02:26:47 +0000161 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=196381 Don't use a list here.
162 // See consumeFontFamilyDescriptor() in CSSPropertyParser.cpp for why we're using it.
163 auto list = CSSValueList::createCommaSeparated();
rniwa@webkit.org02e8c082019-07-25 21:18:04 +0000164 list->append(CSSValuePool::singleton().createFontFamilyValue(familyNameToUse));
mmaxfield@apple.com1fa89ac2019-03-29 02:26:47 +0000165 bool success = m_backing->setFamilies(list);
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000166 if (!success)
cdumez@apple.com750df372017-07-25 03:59:12 +0000167 return Exception { SyntaxError };
darin@apple.comfa677492016-10-17 00:16:05 +0000168 return { };
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000169}
170
darin@apple.comfa677492016-10-17 00:16:05 +0000171ExceptionOr<void> FontFace::setStyle(const String& style)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000172{
darin@apple.comfa677492016-10-17 00:16:05 +0000173 if (style.isEmpty())
cdumez@apple.com750df372017-07-25 03:59:12 +0000174 return Exception { SyntaxError };
mmaxfield@apple.combccd4b92016-05-26 17:08:17 +0000175
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000176 if (auto value = parseString(style, CSSPropertyFontStyle)) {
177 m_backing->setStyle(*value);
178 return { };
179 }
cdumez@apple.com750df372017-07-25 03:59:12 +0000180 return Exception { SyntaxError };
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000181}
182
darin@apple.comfa677492016-10-17 00:16:05 +0000183ExceptionOr<void> FontFace::setWeight(const String& weight)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000184{
darin@apple.comfa677492016-10-17 00:16:05 +0000185 if (weight.isEmpty())
cdumez@apple.com750df372017-07-25 03:59:12 +0000186 return Exception { SyntaxError };
mmaxfield@apple.combccd4b92016-05-26 17:08:17 +0000187
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000188 if (auto value = parseString(weight, CSSPropertyFontWeight)) {
189 m_backing->setWeight(*value);
190 return { };
191 }
cdumez@apple.com750df372017-07-25 03:59:12 +0000192 return Exception { SyntaxError };
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000193}
194
mmaxfield@apple.com10e08fa2017-03-05 20:14:02 +0000195ExceptionOr<void> FontFace::setStretch(const String& stretch)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000196{
mmaxfield@apple.com10e08fa2017-03-05 20:14:02 +0000197 if (stretch.isEmpty())
cdumez@apple.com750df372017-07-25 03:59:12 +0000198 return Exception { SyntaxError };
mmaxfield@apple.com10e08fa2017-03-05 20:14:02 +0000199
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000200 if (auto value = parseString(stretch, CSSPropertyFontStretch)) {
201 m_backing->setStretch(*value);
202 return { };
203 }
cdumez@apple.com750df372017-07-25 03:59:12 +0000204 return Exception { SyntaxError };
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000205}
206
darin@apple.comfa677492016-10-17 00:16:05 +0000207ExceptionOr<void> FontFace::setUnicodeRange(const String& unicodeRange)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000208{
darin@apple.comfa677492016-10-17 00:16:05 +0000209 if (unicodeRange.isEmpty())
cdumez@apple.com750df372017-07-25 03:59:12 +0000210 return Exception { SyntaxError };
mmaxfield@apple.combccd4b92016-05-26 17:08:17 +0000211
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000212 bool success = false;
213 if (auto value = parseString(unicodeRange, CSSPropertyUnicodeRange))
214 success = m_backing->setUnicodeRange(*value);
215 if (!success)
cdumez@apple.com750df372017-07-25 03:59:12 +0000216 return Exception { SyntaxError };
darin@apple.comfa677492016-10-17 00:16:05 +0000217 return { };
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000218}
219
darin@apple.comfa677492016-10-17 00:16:05 +0000220ExceptionOr<void> FontFace::setVariant(const String& variant)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000221{
darin@apple.comfa677492016-10-17 00:16:05 +0000222 if (variant.isEmpty())
cdumez@apple.com750df372017-07-25 03:59:12 +0000223 return Exception { SyntaxError };
mmaxfield@apple.combccd4b92016-05-26 17:08:17 +0000224
darin@apple.comd6016702016-05-07 21:14:20 +0000225 auto style = MutableStyleProperties::create();
hyatt@apple.coma703cf22016-12-14 21:02:07 +0000226 auto result = CSSParser::parseValue(style, CSSPropertyFontVariant, variant, true, HTMLStandardMode);
darin@apple.comfa677492016-10-17 00:16:05 +0000227 if (result == CSSParser::ParseResult::Error)
cdumez@apple.com750df372017-07-25 03:59:12 +0000228 return Exception { SyntaxError };
darin@apple.comd6016702016-05-07 21:14:20 +0000229
230 // FIXME: Would be much better to stage the new settings and set them all at once
231 // instead of this dance where we make a backup and revert to it if something fails.
232 FontVariantSettings backup = m_backing->variantSettings();
233
234 auto normal = CSSValuePool::singleton().createIdentifierValue(CSSValueNormal);
235 bool success = true;
236
237 if (auto value = style->getPropertyCSSValue(CSSPropertyFontVariantLigatures))
238 success &= m_backing->setVariantLigatures(*value);
239 else
240 m_backing->setVariantLigatures(normal);
241
242 if (auto value = style->getPropertyCSSValue(CSSPropertyFontVariantPosition))
243 success &= m_backing->setVariantPosition(*value);
244 else
245 m_backing->setVariantPosition(normal);
246
247 if (auto value = style->getPropertyCSSValue(CSSPropertyFontVariantCaps))
248 success &= m_backing->setVariantCaps(*value);
249 else
250 m_backing->setVariantCaps(normal);
251
252 if (auto value = style->getPropertyCSSValue(CSSPropertyFontVariantNumeric))
253 success &= m_backing->setVariantNumeric(*value);
254 else
255 m_backing->setVariantNumeric(normal);
256
257 if (auto value = style->getPropertyCSSValue(CSSPropertyFontVariantAlternates))
258 success &= m_backing->setVariantAlternates(*value);
259 else
260 m_backing->setVariantAlternates(normal);
261
262 if (auto value = style->getPropertyCSSValue(CSSPropertyFontVariantEastAsian))
263 success &= m_backing->setVariantEastAsian(*value);
264 else
265 m_backing->setVariantEastAsian(normal);
266
267 if (!success) {
268 m_backing->setVariantSettings(backup);
cdumez@apple.com750df372017-07-25 03:59:12 +0000269 return Exception { SyntaxError };
darin@apple.comd6016702016-05-07 21:14:20 +0000270 }
darin@apple.comfa677492016-10-17 00:16:05 +0000271
272 return { };
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000273}
274
darin@apple.comfa677492016-10-17 00:16:05 +0000275ExceptionOr<void> FontFace::setFeatureSettings(const String& featureSettings)
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000276{
darin@apple.comfa677492016-10-17 00:16:05 +0000277 if (featureSettings.isEmpty())
cdumez@apple.com750df372017-07-25 03:59:12 +0000278 return Exception { SyntaxError };
mmaxfield@apple.combccd4b92016-05-26 17:08:17 +0000279
darin@apple.comd6016702016-05-07 21:14:20 +0000280 auto value = parseString(featureSettings, CSSPropertyFontFeatureSettings);
darin@apple.comfa677492016-10-17 00:16:05 +0000281 if (!value)
cdumez@apple.com750df372017-07-25 03:59:12 +0000282 return Exception { SyntaxError };
darin@apple.comd6016702016-05-07 21:14:20 +0000283 m_backing->setFeatureSettings(*value);
darin@apple.comfa677492016-10-17 00:16:05 +0000284 return { };
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000285}
286
mmaxfield@apple.com0d8cd0b2017-10-06 01:25:01 +0000287ExceptionOr<void> FontFace::setDisplay(const String& display)
288{
289 if (display.isEmpty())
290 return Exception { SyntaxError };
291
292 if (auto value = parseString(display, CSSPropertyFontDisplay)) {
293 m_backing->setLoadingBehavior(*value);
294 return { };
295 }
296
297 return Exception { SyntaxError };
298}
299
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000300String FontFace::family() const
301{
darin@apple.com6c71ce22017-01-14 03:35:54 +0000302 m_backing->updateStyleIfNeeded();
mmaxfield@apple.com1fa89ac2019-03-29 02:26:47 +0000303
304 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=196381 This is only here because CSSFontFace erroneously uses a list of values instead of a single value.
305 // See consumeFontFamilyDescriptor() in CSSPropertyParser.cpp.
306 if (m_backing->families()->length() == 1) {
307 if (m_backing->families()->item(0)) {
308 auto& item = *m_backing->families()->item(0);
309 if (item.isPrimitiveValue()) {
310 auto& primitiveValue = downcast<CSSPrimitiveValue>(item);
311 if (primitiveValue.isFontFamily()) {
312 auto& fontFamily = primitiveValue.fontFamily();
313 return fontFamily.familyName;
314 }
315 }
316 }
317 }
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000318 return m_backing->families()->cssText();
319}
320
321String FontFace::style() const
322{
darin@apple.com6c71ce22017-01-14 03:35:54 +0000323 m_backing->updateStyleIfNeeded();
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000324 auto style = m_backing->italic();
325
mmaxfield@apple.coma266d032017-05-23 07:37:42 +0000326 auto minimum = ComputedStyleExtractor::fontStyleFromStyleValue(style.minimum, FontStyleAxis::ital);
327 auto maximum = ComputedStyleExtractor::fontStyleFromStyleValue(style.maximum, FontStyleAxis::ital);
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000328
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000329 if (minimum.get().equals(maximum.get()))
330 return minimum->cssText();
331
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000332 auto minimumNonKeyword = ComputedStyleExtractor::fontNonKeywordStyleFromStyleValue(style.minimum);
333 auto maximumNonKeyword = ComputedStyleExtractor::fontNonKeywordStyleFromStyleValue(style.maximum);
334
335 ASSERT(minimumNonKeyword->fontStyleValue->valueID() == CSSValueOblique);
336 ASSERT(maximumNonKeyword->fontStyleValue->valueID() == CSSValueOblique);
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000337
338 StringBuilder builder;
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000339 builder.append(minimumNonKeyword->fontStyleValue->cssText());
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000340 builder.append(' ');
341 if (minimum->obliqueValue.get() == maximum->obliqueValue.get())
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000342 builder.append(minimumNonKeyword->obliqueValue->cssText());
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000343 else {
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000344 builder.append(minimumNonKeyword->obliqueValue->cssText());
345 builder.append(' ');
346 builder.append(maximumNonKeyword->obliqueValue->cssText());
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000347 }
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000348 return builder.toString();
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000349}
350
351String FontFace::weight() const
352{
darin@apple.com6c71ce22017-01-14 03:35:54 +0000353 m_backing->updateStyleIfNeeded();
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000354 auto weight = m_backing->weight();
355
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000356 auto minimum = ComputedStyleExtractor::fontWeightFromStyleValue(weight.minimum);
357 auto maximum = ComputedStyleExtractor::fontWeightFromStyleValue(weight.maximum);
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000358
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000359 if (minimum.get().equals(maximum.get()))
360 return minimum->cssText();
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000361
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000362 auto minimumNonKeyword = ComputedStyleExtractor::fontNonKeywordWeightFromStyleValue(weight.minimum);
363 auto maximumNonKeyword = ComputedStyleExtractor::fontNonKeywordWeightFromStyleValue(weight.maximum);
364
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000365 StringBuilder builder;
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000366 builder.append(minimumNonKeyword->cssText());
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000367 builder.append(' ');
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000368 builder.append(maximumNonKeyword->cssText());
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000369 return builder.toString();
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000370}
371
372String FontFace::stretch() const
373{
mmaxfield@apple.com10e08fa2017-03-05 20:14:02 +0000374 m_backing->updateStyleIfNeeded();
375 auto stretch = m_backing->stretch();
376
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000377 auto minimum = ComputedStyleExtractor::fontStretchFromStyleValue(stretch.minimum);
378 auto maximum = ComputedStyleExtractor::fontStretchFromStyleValue(stretch.maximum);
mmaxfield@apple.com10e08fa2017-03-05 20:14:02 +0000379
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000380 if (minimum.get().equals(maximum.get()))
381 return minimum->cssText();
mmaxfield@apple.com851f3942017-03-06 21:40:31 +0000382
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000383 auto minimumNonKeyword = ComputedStyleExtractor::fontNonKeywordStretchFromStyleValue(stretch.minimum);
384 auto maximumNonKeyword = ComputedStyleExtractor::fontNonKeywordStretchFromStyleValue(stretch.maximum);
385
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000386 StringBuilder builder;
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000387 builder.append(minimumNonKeyword->cssText());
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000388 builder.append(' ');
mmaxfield@apple.com2bd2add2017-03-27 22:09:14 +0000389 builder.append(maximumNonKeyword->cssText());
mmaxfield@apple.com076f8a02017-03-27 17:50:33 +0000390 return builder.toString();
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000391}
392
393String FontFace::unicodeRange() const
394{
darin@apple.com6c71ce22017-01-14 03:35:54 +0000395 m_backing->updateStyleIfNeeded();
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000396 if (!m_backing->ranges().size())
utatane.tea@gmail.com84077632018-06-23 08:39:34 +0000397 return "U+0-10FFFF"_s;
yusukesuzuki@slowstart.orgae5a8bd2018-12-22 06:37:39 +0000398 auto values = CSSValueList::createCommaSeparated();
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000399 for (auto& range : m_backing->ranges())
darin@apple.comd6016702016-05-07 21:14:20 +0000400 values->append(CSSUnicodeRangeValue::create(range.from, range.to));
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000401 return values->cssText();
402}
403
404String FontFace::variant() const
405{
darin@apple.com6c71ce22017-01-14 03:35:54 +0000406 m_backing->updateStyleIfNeeded();
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000407 return computeFontVariant(m_backing->variantSettings())->cssText();
408}
409
410String FontFace::featureSettings() const
411{
darin@apple.com6c71ce22017-01-14 03:35:54 +0000412 m_backing->updateStyleIfNeeded();
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000413 if (!m_backing->featureSettings().size())
utatane.tea@gmail.com84077632018-06-23 08:39:34 +0000414 return "normal"_s;
yusukesuzuki@slowstart.orgae5a8bd2018-12-22 06:37:39 +0000415 auto list = CSSValueList::createCommaSeparated();
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000416 for (auto& feature : m_backing->featureSettings())
mmaxfield@apple.com0befb732016-09-30 21:11:21 +0000417 list->append(CSSFontFeatureValue::create(FontTag(feature.tag()), feature.value()));
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000418 return list->cssText();
419}
420
mmaxfield@apple.com0d8cd0b2017-10-06 01:25:01 +0000421String FontFace::display() const
422{
423 m_backing->updateStyleIfNeeded();
424 return CSSValuePool::singleton().createValue(m_backing->loadingBehavior())->cssText();
425}
426
darin@apple.com53438e92016-05-03 05:47:34 +0000427auto FontFace::status() const -> LoadStatus
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000428{
429 switch (m_backing->status()) {
430 case CSSFontFace::Status::Pending:
darin@apple.com53438e92016-05-03 05:47:34 +0000431 return LoadStatus::Unloaded;
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000432 case CSSFontFace::Status::Loading:
darin@apple.com53438e92016-05-03 05:47:34 +0000433 return LoadStatus::Loading;
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000434 case CSSFontFace::Status::TimedOut:
darin@apple.com53438e92016-05-03 05:47:34 +0000435 return LoadStatus::Error;
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000436 case CSSFontFace::Status::Success:
darin@apple.com53438e92016-05-03 05:47:34 +0000437 return LoadStatus::Loaded;
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000438 case CSSFontFace::Status::Failure:
darin@apple.com53438e92016-05-03 05:47:34 +0000439 return LoadStatus::Error;
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000440 }
441 ASSERT_NOT_REACHED();
darin@apple.com53438e92016-05-03 05:47:34 +0000442 return LoadStatus::Error;
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000443}
444
mmaxfield@apple.com75cccd62016-06-11 17:52:35 +0000445void FontFace::adopt(CSSFontFace& newFace)
446{
mmaxfield@apple.com75cccd62016-06-11 17:52:35 +0000447 m_backing->removeClient(*this);
448 m_backing = newFace;
449 m_backing->addClient(*this);
450 newFace.setWrapper(*this);
451}
452
mmaxfield@apple.com2b428902016-02-22 21:40:02 +0000453void FontFace::fontStateChanged(CSSFontFace& face, CSSFontFace::Status, CSSFontFace::Status newState)
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000454{
455 ASSERT_UNUSED(face, &face == m_backing.ptr());
mmaxfield@apple.com7c336912016-02-18 07:25:56 +0000456 switch (newState) {
mmaxfield@apple.com2b428902016-02-22 21:40:02 +0000457 case CSSFontFace::Status::Loading:
458 // We still need to resolve promises when loading completes, even if all references to use have fallen out of scope.
459 ref();
460 break;
mmaxfield@apple.com2a6a4ba2016-06-04 02:00:50 +0000461 case CSSFontFace::Status::TimedOut:
462 break;
youenn.fablet@crf.canon.fr6bc37942016-05-07 20:04:27 +0000463 case CSSFontFace::Status::Success:
weinig@apple.com5a46ef02017-08-09 01:01:44 +0000464 // FIXME: This check should not be needed, but because FontFace's are sometimes adopted after they have already
465 // gone through a load cycle, we can sometimes come back through here and try to resolve the promise again.
466 if (!m_loadedPromise.isFulfilled())
467 m_loadedPromise.resolve(*this);
mmaxfield@apple.com2b428902016-02-22 21:40:02 +0000468 deref();
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000469 return;
youenn.fablet@crf.canon.fr6bc37942016-05-07 20:04:27 +0000470 case CSSFontFace::Status::Failure:
weinig@apple.com5a46ef02017-08-09 01:01:44 +0000471 // FIXME: This check should not be needed, but because FontFace's are sometimes adopted after they have already
472 // gone through a load cycle, we can sometimes come back through here and try to resolve the promise again.
473 if (!m_loadedPromise.isFulfilled())
474 m_loadedPromise.reject(Exception { NetworkError });
youenn.fablet@crf.canon.fr6bc37942016-05-07 20:04:27 +0000475 deref();
476 return;
477 case CSSFontFace::Status::Pending:
478 ASSERT_NOT_REACHED();
479 return;
480 }
481}
482
weinig@apple.com5a46ef02017-08-09 01:01:44 +0000483auto FontFace::load() -> LoadedPromise&
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000484{
485 m_backing->load();
weinig@apple.com5a46ef02017-08-09 01:01:44 +0000486 return m_loadedPromise;
487}
488
commit-queue@webkit.org06fd6462017-08-12 00:32:03 +0000489FontFace& FontFace::loadedPromiseResolve()
weinig@apple.com5a46ef02017-08-09 01:01:44 +0000490{
commit-queue@webkit.org06fd6462017-08-12 00:32:03 +0000491 return *this;
mmaxfield@apple.comf48289b2016-02-15 23:39:02 +0000492}
493
mmaxfield@apple.com216d5f12016-02-12 22:22:20 +0000494}