Add modern API for overriding the page's specified viewport configuration
[WebKit-https.git] / Source / WebCore / css / CSSSegmentedFontFace.cpp
1 /*
2  * Copyright (C) 2008, 2013 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 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 "CSSSegmentedFontFace.h"
28
29 #include "CSSFontFace.h"
30 #include "Font.h"
31 #include "FontCache.h"
32 #include "FontDescription.h"
33 #include "FontSelector.h"
34
35 namespace WebCore {
36
37 CSSSegmentedFontFace::CSSSegmentedFontFace()
38 {
39 }
40
41 CSSSegmentedFontFace::~CSSSegmentedFontFace()
42 {
43     for (auto& face : m_fontFaces)
44         face->removeClient(*this);
45 }
46
47 void CSSSegmentedFontFace::appendFontFace(Ref<CSSFontFace>&& fontFace)
48 {
49     m_cache.clear();
50     fontFace->addClient(*this);
51     m_fontFaces.append(WTFMove(fontFace));
52 }
53
54 void CSSSegmentedFontFace::fontLoaded(CSSFontFace&)
55 {
56     m_cache.clear();
57 }
58
59 class CSSFontAccessor final : public FontAccessor {
60 public:
61     static Ref<CSSFontAccessor> create(CSSFontFace& fontFace, const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic)
62     {
63         return adoptRef(*new CSSFontAccessor(fontFace, fontDescription, syntheticBold, syntheticItalic));
64     }
65
66     const Font* font(ExternalResourceDownloadPolicy policy) const final
67     {
68         if (!m_result || (policy == ExternalResourceDownloadPolicy::Allow
69             && (m_fontFace->status() == CSSFontFace::Status::Pending || m_fontFace->status() == CSSFontFace::Status::Loading || m_fontFace->status() == CSSFontFace::Status::TimedOut))) {
70             const auto result = m_fontFace->font(m_fontDescription, m_syntheticBold, m_syntheticItalic, policy);
71             if (!m_result)
72                 m_result = result;
73         }
74         return m_result.value().get();
75     }
76
77 private:
78     CSSFontAccessor(CSSFontFace& fontFace, const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic)
79         : m_fontFace(fontFace)
80         , m_fontDescription(fontDescription)
81         , m_syntheticBold(syntheticBold)
82         , m_syntheticItalic(syntheticItalic)
83     {
84     }
85
86     bool isLoading() const final
87     {
88         return m_result && m_result.value() && m_result.value()->isInterstitial();
89     }
90
91     mutable Optional<RefPtr<Font>> m_result; // Caches nullptr too
92     mutable Ref<CSSFontFace> m_fontFace;
93     FontDescription m_fontDescription;
94     bool m_syntheticBold;
95     bool m_syntheticItalic;
96 };
97
98 static void appendFont(FontRanges& ranges, Ref<FontAccessor>&& fontAccessor, const Vector<CSSFontFace::UnicodeRange>& unicodeRanges)
99 {
100     if (unicodeRanges.isEmpty()) {
101         ranges.appendRange({ 0, 0x7FFFFFFF, WTFMove(fontAccessor) });
102         return;
103     }
104
105     for (auto& range : unicodeRanges)
106         ranges.appendRange({ range.from, range.to, fontAccessor.copyRef() });
107 }
108
109 FontRanges CSSSegmentedFontFace::fontRanges(const FontDescription& fontDescription)
110 {
111     auto desiredRequest = fontDescription.fontSelectionRequest();
112
113     auto addResult = m_cache.add(FontDescriptionKey(fontDescription), FontRanges());
114     auto& result = addResult.iterator->value;
115
116     if (addResult.isNewEntry) {
117         for (auto& face : m_fontFaces) {
118             if (face->computeFailureState())
119                 continue;
120
121             auto selectionCapabilities = face->fontSelectionCapabilities();
122             bool syntheticBold = (fontDescription.fontSynthesis() & FontSynthesisWeight) && !isFontWeightBold(selectionCapabilities.weight.maximum) && isFontWeightBold(desiredRequest.weight);
123             bool syntheticItalic = (fontDescription.fontSynthesis() & FontSynthesisStyle) && !isItalic(selectionCapabilities.slope.maximum) && isItalic(desiredRequest.slope);
124
125             // Metrics used for layout come from FontRanges::fontForFirstRange(), which assumes that the first font is non-null.
126             auto fontAccessor = CSSFontAccessor::create(face, fontDescription, syntheticBold, syntheticItalic);
127             if (result.isNull() && !fontAccessor->font(ExternalResourceDownloadPolicy::Forbid))
128                 continue;
129             appendFont(result, WTFMove(fontAccessor), face->ranges());
130         }
131     }
132     return result;
133 }
134
135 }