1/*
2 * Copyright (C) 2008, 2009, 2015 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 "FontRanges.h"
28
29#include "Font.h"
30#include "FontSelector.h"
31#include <wtf/Assertions.h>
32#include <wtf/text/WTFString.h>
33
34namespace WebCore {
35
36const Font* FontRanges::Range::font(ExternalResourceDownloadPolicy policy) const
37{
38 return m_fontAccessor->font(policy);
39}
40
41FontRanges::FontRanges() = default;
42
43class TrivialFontAccessor final : public FontAccessor {
44public:
45 static Ref<TrivialFontAccessor> create(Ref<Font>&& font)
46 {
47 return adoptRef(*new TrivialFontAccessor(WTFMove(font)));
48 }
49
50private:
51 TrivialFontAccessor(RefPtr<Font>&& font)
52 : m_font(WTFMove(font))
53 {
54 }
55
56 const Font* font(ExternalResourceDownloadPolicy) const final
57 {
58 return m_font.get();
59 }
60
61 bool isLoading() const final
62 {
63 return m_font->isInterstitial();
64 }
65
66 RefPtr<Font> m_font;
67};
68
69FontRanges::FontRanges(RefPtr<Font>&& font)
70{
71 if (font)
72 m_ranges.append(Range { 0, 0x7FFFFFFF, TrivialFontAccessor::create(font.releaseNonNull()) });
73}
74
75FontRanges::~FontRanges() = default;
76
77GlyphData FontRanges::glyphDataForCharacter(UChar32 character, ExternalResourceDownloadPolicy policy) const
78{
79 const Font* resultFont = nullptr;
80 for (auto& range : m_ranges) {
81 if (range.from() <= character && character <= range.to()) {
82 if (auto* font = range.font(policy)) {
83 if (font->isInterstitial()) {
84 policy = ExternalResourceDownloadPolicy::Forbid;
85 if (!resultFont)
86 resultFont = font;
87 } else {
88 auto glyphData = font->glyphDataForCharacter(character);
89 if (glyphData.glyph) {
90 auto* glyphDataFont = glyphData.font;
91 if (glyphDataFont && glyphDataFont->visibility() == Font::Visibility::Visible && resultFont && resultFont->visibility() == Font::Visibility::Invisible)
92 return GlyphData(glyphData.glyph, &glyphDataFont->invisibleFont());
93 return glyphData;
94 }
95 }
96 }
97 }
98 }
99 if (resultFont) {
100 // We want higher-level code to be able to differentiate between
101 // "The interstitial font doesn't have the character" and
102 // "The real downloaded font doesn't have the character".
103 GlyphData result = resultFont->glyphDataForCharacter(character);
104 if (!result.font)
105 result.font = resultFont;
106 return result;
107 }
108 return GlyphData();
109}
110
111const Font* FontRanges::fontForCharacter(UChar32 character) const
112{
113 return glyphDataForCharacter(character, ExternalResourceDownloadPolicy::Allow).font;
114}
115
116const Font& FontRanges::fontForFirstRange() const
117{
118 auto* font = m_ranges[0].font(ExternalResourceDownloadPolicy::Forbid);
119 ASSERT(font);
120 return *font;
121}
122
123bool FontRanges::isLoading() const
124{
125 for (auto& range : m_ranges) {
126 if (range.fontAccessor().isLoading())
127 return true;
128 }
129 return false;
130}
131
132} // namespace WebCore
133