Keep auxilliary media objects on the heap always.
[chromium-blink-merge.git] / third_party / WebKit / Source / core / html / canvas / CanvasFontCache.cpp
blob2673c3339f9ce649fe31b68a8fd363453c53ab9b
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "config.h"
7 #include "core/html/canvas/CanvasFontCache.h"
9 #include "core/css/parser/CSSParser.h"
10 #include "core/css/resolver/StyleResolver.h"
11 #include "core/dom/Document.h"
12 #include "core/style/ComputedStyle.h"
13 #include "platform/fonts/FontCache.h"
14 #include "public/platform/Platform.h"
16 namespace {
18 const unsigned CanvasFontCacheMaxFonts = 50;
19 const unsigned CanvasFontCacheHardMaxFonts = 250;
20 const unsigned CanvasFontCacheHiddenMaxFonts = 1;
21 const int defaultFontSize = 10;
22 const char defaultFontFamily[] = "sans-serif";
26 namespace blink {
28 CanvasFontCache::CanvasFontCache(Document& document)
29 : m_document(&document)
30 , m_pruningScheduled(false)
32 FontFamily fontFamily;
33 fontFamily.setFamily(defaultFontFamily);
34 FontDescription defaultFontDescription;
35 defaultFontDescription.setFamily(fontFamily);
36 defaultFontDescription.setSpecifiedSize(defaultFontSize);
37 defaultFontDescription.setComputedSize(defaultFontSize);
38 m_defaultFontStyle = ComputedStyle::create();
39 m_defaultFontStyle->setFontDescription(defaultFontDescription);
40 m_defaultFontStyle->font().update(m_defaultFontStyle->font().fontSelector());
43 CanvasFontCache::~CanvasFontCache()
45 m_mainCachePurgePreventer.clear();
46 if (m_pruningScheduled) {
47 Platform::current()->currentThread()->removeTaskObserver(this);
51 unsigned CanvasFontCache::maxFonts()
53 return CanvasFontCacheMaxFonts;
56 unsigned CanvasFontCache::hardMaxFonts()
58 return m_document->hidden() ? CanvasFontCacheHiddenMaxFonts : CanvasFontCacheHardMaxFonts;
61 bool CanvasFontCache::getFontUsingDefaultStyle(const String& fontString, Font& resolvedFont)
63 HashMap<String, Font>::iterator i = m_fontsResolvedUsingDefaultStyle.find(fontString);
64 if (i != m_fontsResolvedUsingDefaultStyle.end()) {
65 ASSERT(m_fontLRUList.contains(fontString));
66 m_fontLRUList.remove(fontString);
67 m_fontLRUList.add(fontString);
68 resolvedFont = i->value;
69 return true;
72 // Addition to LRU list taken care of inside parseFont
73 MutableStylePropertySet* parsedStyle = parseFont(fontString);
74 if (!parsedStyle)
75 return false;
77 RefPtr<ComputedStyle> fontStyle = ComputedStyle::clone(*m_defaultFontStyle.get());
78 m_document->ensureStyleResolver().computeFont(fontStyle.get(), *parsedStyle);
79 m_fontsResolvedUsingDefaultStyle.add(fontString, fontStyle->font());
80 resolvedFont = m_fontsResolvedUsingDefaultStyle.find(fontString)->value;
81 return true;
84 MutableStylePropertySet* CanvasFontCache::parseFont(const String& fontString)
86 RefPtrWillBeRawPtr<MutableStylePropertySet> parsedStyle;
87 MutableStylePropertyMap::iterator i = m_fetchedFonts.find(fontString);
88 if (i != m_fetchedFonts.end()) {
89 ASSERT(m_fontLRUList.contains(fontString));
90 parsedStyle = i->value;
91 m_fontLRUList.remove(fontString);
92 m_fontLRUList.add(fontString);
93 } else {
94 parsedStyle = MutableStylePropertySet::create();
95 CSSParser::parseValue(parsedStyle.get(), CSSPropertyFont, fontString, true, HTMLStandardMode, 0);
96 if (parsedStyle->isEmpty())
97 return nullptr;
98 // According to http://lists.w3.org/Archives/Public/public-html/2009Jul/0947.html,
99 // the "inherit" and "initial" values must be ignored.
100 RefPtrWillBeRawPtr<CSSValue> fontValue = parsedStyle->getPropertyCSSValue(CSSPropertyFontSize);
101 if (fontValue && (fontValue->isInitialValue() || fontValue->isInheritedValue()))
102 return nullptr;
103 m_fetchedFonts.add(fontString, parsedStyle);
104 m_fontLRUList.add(fontString);
105 // Hard limit is applied here, on the fly, while the soft limit is
106 // applied at the end of the task.
107 if (m_fetchedFonts.size() > hardMaxFonts()) {
108 ASSERT(m_fetchedFonts.size() == hardMaxFonts() + 1);
109 ASSERT(m_fontLRUList.size() == hardMaxFonts() + 1);
110 m_fetchedFonts.remove(m_fontLRUList.first());
111 m_fontsResolvedUsingDefaultStyle.remove(m_fontLRUList.first());
112 m_fontLRUList.removeFirst();
115 schedulePruningIfNeeded();
117 return parsedStyle.get(); // In non-oilpan builds: ref in m_fetchedFonts keeps object alive after return.
120 void CanvasFontCache::didProcessTask()
122 ASSERT(m_pruningScheduled);
123 ASSERT(m_mainCachePurgePreventer);
124 while (m_fetchedFonts.size() > maxFonts()) {
125 m_fetchedFonts.remove(m_fontLRUList.first());
126 m_fontsResolvedUsingDefaultStyle.remove(m_fontLRUList.first());
127 m_fontLRUList.removeFirst();
129 m_mainCachePurgePreventer.clear();
130 Platform::current()->currentThread()->removeTaskObserver(this);
131 m_pruningScheduled = false;
134 void CanvasFontCache::schedulePruningIfNeeded()
136 if (m_pruningScheduled)
137 return;
138 ASSERT(!m_mainCachePurgePreventer);
139 m_mainCachePurgePreventer = adoptPtr(new FontCachePurgePreventer);
140 Platform::current()->currentThread()->addTaskObserver(this);
141 m_pruningScheduled = true;
144 bool CanvasFontCache::isInCache(const String& fontString)
146 return m_fetchedFonts.find(fontString) != m_fetchedFonts.end();
149 void CanvasFontCache::pruneAll()
151 m_fetchedFonts.clear();
152 m_fontLRUList.clear();
153 m_fontsResolvedUsingDefaultStyle.clear();
156 DEFINE_TRACE(CanvasFontCache)
158 #if ENABLE(OILPAN)
159 visitor->trace(m_fetchedFonts);
160 visitor->trace(m_document);
161 #endif
164 } // blink