52aac753dd1919c9872263ecafc7ceb97c8817de
[WebKit-https.git] / Source / WebCore / css / CSSFontFaceSource.cpp
1 /*
2  * Copyright (C) 2007, 2008, 2010, 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 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 "CSSFontFaceSource.h"
28
29 #include "CSSFontFace.h"
30 #include "CSSFontSelector.h"
31 #include "CachedFont.h"
32 #include "Document.h"
33 #include "Font.h"
34 #include "FontCache.h"
35 #include "FontCustomPlatformData.h"
36 #include "FontDescription.h"
37 #include "SVGToOTFFontConversion.h"
38 #include "SharedBuffer.h"
39
40 #if ENABLE(SVG_FONTS)
41 #include "CachedSVGFont.h"
42 #include "FontCustomPlatformData.h"
43 #include "SVGFontElement.h"
44 #include "SVGFontFaceElement.h"
45 #include "SVGURIReference.h"
46 #endif
47
48 #if USE(DIRECT2D)
49 #include <dwrite.h>
50 #endif
51
52 namespace WebCore {
53
54 inline void CSSFontFaceSource::setStatus(Status newStatus)
55 {
56     switch (newStatus) {
57     case Status::Pending:
58         ASSERT_NOT_REACHED();
59         break;
60     case Status::Loading:
61         ASSERT(status() == Status::Pending);
62         break;
63     case Status::Success:
64         ASSERT(status() == Status::Loading);
65         break;
66     case Status::Failure:
67         ASSERT(status() == Status::Loading);
68         break;
69     }
70
71     m_status = newStatus;
72 }
73
74 CSSFontFaceSource::CSSFontFaceSource(CSSFontFace& owner, const String& familyNameOrURI, CachedFont* font, SVGFontFaceElement* fontFace, RefPtr<JSC::ArrayBufferView>&& arrayBufferView)
75     : m_familyNameOrURI(familyNameOrURI)
76     , m_font(font)
77     , m_face(owner)
78     , m_immediateSource(WTFMove(arrayBufferView))
79 #if ENABLE(SVG_FONTS)
80     , m_svgFontFaceElement(fontFace)
81 #endif
82 {
83 #if !ENABLE(SVG_FONTS)
84     UNUSED_PARAM(fontFace);
85 #endif
86
87     // This may synchronously call fontLoaded().
88     if (m_font)
89         m_font->addClient(*this);
90
91     if (status() == Status::Pending && m_font && m_font->isLoaded()) {
92         setStatus(Status::Loading);
93         if (m_font && m_font->errorOccurred())
94             setStatus(Status::Failure);
95         else
96             setStatus(Status::Success);
97     }
98 }
99
100 CSSFontFaceSource::~CSSFontFaceSource()
101 {
102     if (m_font)
103         m_font->removeClient(*this);
104 }
105
106 void CSSFontFaceSource::fontLoaded(CachedFont& loadedFont)
107 {
108     ASSERT_UNUSED(loadedFont, &loadedFont == m_font.get());
109
110     Ref<CSSFontFace> protectedFace(m_face);
111
112     // If the font is in the cache, this will be synchronously called from CachedFont::addClient().
113     if (m_status == Status::Pending)
114         setStatus(Status::Loading);
115     else if (m_status == Status::Failure) {
116         // This function may be called twice if loading was cancelled.
117         ASSERT(m_font->errorOccurred());
118         return;
119     }
120
121     if (m_face.webFontsShouldAlwaysFallBack())
122         return;
123
124     if (m_font->errorOccurred() || !m_font->ensureCustomFontData(m_familyNameOrURI))
125         setStatus(Status::Failure);
126     else
127         setStatus(Status::Success);
128
129     m_face.fontLoaded(*this);
130 }
131
132 void CSSFontFaceSource::load(CSSFontSelector* fontSelector)
133 {
134     setStatus(Status::Loading);
135
136     if (m_font) {
137         ASSERT(fontSelector);
138         fontSelector->beginLoadingFontSoon(*m_font);
139     } else {
140         bool success = false;
141 #if ENABLE(SVG_FONTS)
142         if (m_svgFontFaceElement) {
143             if (is<SVGFontElement>(m_svgFontFaceElement->parentNode())) {
144                 ASSERT(!m_inDocumentCustomPlatformData);
145                 SVGFontElement& fontElement = downcast<SVGFontElement>(*m_svgFontFaceElement->parentNode());
146                 if (auto otfFont = convertSVGToOTFFont(fontElement))
147                     m_generatedOTFBuffer = SharedBuffer::create(WTFMove(otfFont.value()));
148                 if (m_generatedOTFBuffer) {
149                     m_inDocumentCustomPlatformData = createFontCustomPlatformData(*m_generatedOTFBuffer);
150                     success = static_cast<bool>(m_inDocumentCustomPlatformData);
151                 }
152             }
153         } else
154 #endif
155         if (m_immediateSource) {
156             ASSERT(!m_immediateFontCustomPlatformData);
157             bool wrapping;
158             RefPtr<SharedBuffer> buffer = SharedBuffer::create(static_cast<const char*>(m_immediateSource->baseAddress()), m_immediateSource->byteLength());
159             ASSERT(buffer);
160             m_immediateFontCustomPlatformData = CachedFont::createCustomFontData(*buffer, wrapping);
161             success = static_cast<bool>(m_immediateFontCustomPlatformData);
162         } else {
163             // We are only interested in whether or not fontForFamily() returns null or not. Luckily, none of
164             // the values in the FontDescription other than the family name can cause the function to return
165             // null if it wasn't going to otherwise (and vice-versa).
166             FontCascadeDescription fontDescription;
167             fontDescription.setOneFamily(m_familyNameOrURI);
168             fontDescription.setComputedSize(1);
169             success = FontCache::singleton().fontForFamily(fontDescription, m_familyNameOrURI, nullptr, nullptr, FontSelectionSpecifiedCapabilities(), true);
170         }
171         setStatus(success ? Status::Success : Status::Failure);
172     }
173 }
174
175 RefPtr<Font> CSSFontFaceSource::font(const FontDescription& fontDescription, bool syntheticBold, bool syntheticItalic, const FontFeatureSettings& fontFaceFeatures, const FontVariantSettings& fontFaceVariantSettings, FontSelectionSpecifiedCapabilities fontFaceCapabilities)
176 {
177     ASSERT(status() == Status::Success);
178
179     SVGFontFaceElement* fontFaceElement = nullptr;
180 #if ENABLE(SVG_FONTS)
181     fontFaceElement = m_svgFontFaceElement.get();
182 #endif
183
184     if (!m_font && !fontFaceElement) {
185         if (m_immediateSource) {
186             if (!m_immediateFontCustomPlatformData)
187                 return nullptr;
188             return Font::create(CachedFont::platformDataFromCustomData(*m_immediateFontCustomPlatformData, fontDescription, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings, fontFaceCapabilities), Font::Origin::Remote);
189         }
190
191         // We're local. Just return a Font from the normal cache.
192         // We don't want to check alternate font family names here, so pass true as the checkingAlternateName parameter.
193         return FontCache::singleton().fontForFamily(fontDescription, m_familyNameOrURI, &fontFaceFeatures, &fontFaceVariantSettings, fontFaceCapabilities, true);
194     }
195
196     if (m_font) {
197         auto success = m_font->ensureCustomFontData(m_familyNameOrURI);
198         ASSERT_UNUSED(success, success);
199
200         ASSERT(status() == Status::Success);
201         auto result = m_font->createFont(fontDescription, m_familyNameOrURI, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings, fontFaceCapabilities);
202         ASSERT(result);
203         return result;
204     }
205
206     // In-Document SVG Fonts
207     if (!fontFaceElement)
208         return nullptr;
209
210 #if ENABLE(SVG_FONTS)
211     if (!is<SVGFontElement>(m_svgFontFaceElement->parentNode()))
212         return nullptr;
213     if (!m_inDocumentCustomPlatformData)
214         return nullptr;
215 #if PLATFORM(COCOA)
216     return Font::create(m_inDocumentCustomPlatformData->fontPlatformData(fontDescription, syntheticBold, syntheticItalic, fontFaceFeatures, fontFaceVariantSettings, fontFaceCapabilities), Font::Origin::Remote);
217 #else
218     return Font::create(m_inDocumentCustomPlatformData->fontPlatformData(fontDescription, syntheticBold, syntheticItalic), Font::Origin::Remote);
219 #endif
220 #endif
221
222     ASSERT_NOT_REACHED();
223     return nullptr;
224 }
225
226 #if ENABLE(SVG_FONTS)
227 bool CSSFontFaceSource::isSVGFontFaceSource() const
228 {
229     return m_svgFontFaceElement || is<CachedSVGFont>(m_font.get());
230 }
231 #endif
232
233 }