OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/font_render_params.h" | 5 #include "ui/gfx/font_render_params.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/containers/mru_cache.h" |
| 9 #include "base/hash.h" |
8 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/macros.h" |
| 12 #include "base/strings/string_util.h" |
| 13 #include "base/strings/stringprintf.h" |
9 #include "ui/gfx/font.h" | 14 #include "ui/gfx/font.h" |
10 #include "ui/gfx/linux_font_delegate.h" | 15 #include "ui/gfx/linux_font_delegate.h" |
11 #include "ui/gfx/switches.h" | 16 #include "ui/gfx/switches.h" |
12 | 17 |
13 #include <fontconfig/fontconfig.h> | 18 #include <fontconfig/fontconfig.h> |
14 | 19 |
15 namespace gfx { | 20 namespace gfx { |
16 | 21 |
17 namespace { | 22 namespace { |
18 | 23 |
| 24 // Should cache entries by dropped by the next call to GetFontRenderParams()? |
| 25 // Used for tests. |
| 26 bool g_clear_cache_for_test = false; |
| 27 |
| 28 // Number of recent GetFontRenderParams() results to cache. |
| 29 const size_t kCacheSize = 10; |
| 30 |
19 // Converts Fontconfig FC_HINT_STYLE to FontRenderParams::Hinting. | 31 // Converts Fontconfig FC_HINT_STYLE to FontRenderParams::Hinting. |
20 FontRenderParams::Hinting ConvertFontconfigHintStyle(int hint_style) { | 32 FontRenderParams::Hinting ConvertFontconfigHintStyle(int hint_style) { |
21 switch (hint_style) { | 33 switch (hint_style) { |
22 case FC_HINT_SLIGHT: return FontRenderParams::HINTING_SLIGHT; | 34 case FC_HINT_SLIGHT: return FontRenderParams::HINTING_SLIGHT; |
23 case FC_HINT_MEDIUM: return FontRenderParams::HINTING_MEDIUM; | 35 case FC_HINT_MEDIUM: return FontRenderParams::HINTING_MEDIUM; |
24 case FC_HINT_FULL: return FontRenderParams::HINTING_FULL; | 36 case FC_HINT_FULL: return FontRenderParams::HINTING_FULL; |
25 default: return FontRenderParams::HINTING_NONE; | 37 default: return FontRenderParams::HINTING_NONE; |
26 } | 38 } |
27 } | 39 } |
28 | 40 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
107 | 119 |
108 int fc_rgba = FC_RGBA_NONE; | 120 int fc_rgba = FC_RGBA_NONE; |
109 if (FcPatternGetInteger(match, FC_RGBA, 0, &fc_rgba) == FcResultMatch) | 121 if (FcPatternGetInteger(match, FC_RGBA, 0, &fc_rgba) == FcResultMatch) |
110 params_out->subpixel_rendering = ConvertFontconfigRgba(fc_rgba); | 122 params_out->subpixel_rendering = ConvertFontconfigRgba(fc_rgba); |
111 } | 123 } |
112 | 124 |
113 FcPatternDestroy(match); | 125 FcPatternDestroy(match); |
114 return true; | 126 return true; |
115 } | 127 } |
116 | 128 |
| 129 // Serialize |query| into a string and hash it to a value suitable for use as a |
| 130 // cache key. |
| 131 uint32 HashFontRenderParamsQuery(const FontRenderParamsQuery& query) { |
| 132 return base::Hash(base::StringPrintf("%d|%d|%d|%d|%s", |
| 133 query.for_web_contents, query.pixel_size, query.point_size, query.style, |
| 134 JoinString(query.families, ',').c_str())); |
| 135 } |
| 136 |
117 } // namespace | 137 } // namespace |
118 | 138 |
119 FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query, | 139 FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query, |
120 std::string* family_out) { | 140 std::string* family_out) { |
121 if (family_out) | 141 typedef base::MRUCache<uint32, FontRenderParams> Cache; |
| 142 CR_DEFINE_STATIC_LOCAL(Cache, cache, (kCacheSize)); |
| 143 |
| 144 if (g_clear_cache_for_test) { |
| 145 cache.Clear(); |
| 146 g_clear_cache_for_test = false; |
| 147 } |
| 148 |
| 149 const uint32 hash = HashFontRenderParamsQuery(query); |
| 150 if (!family_out) { |
| 151 // The family returned by Fontconfig isn't part of FontRenderParams, so we |
| 152 // can only return a value from the cache if it wasn't requested. |
| 153 Cache::const_iterator it = cache.Get(hash); |
| 154 if (it != cache.end()) { |
| 155 DVLOG(1) << "Returning cached params for " << hash; |
| 156 return it->second; |
| 157 } |
| 158 } else { |
122 family_out->clear(); | 159 family_out->clear(); |
| 160 } |
| 161 DVLOG(1) << "Computing params for " << hash |
| 162 << (family_out ? " (family requested)" : ""); |
123 | 163 |
124 // Start with the delegate's settings, but let Fontconfig have the final say. | 164 // Start with the delegate's settings, but let Fontconfig have the final say. |
125 FontRenderParams params; | 165 FontRenderParams params; |
126 const LinuxFontDelegate* delegate = LinuxFontDelegate::instance(); | 166 const LinuxFontDelegate* delegate = LinuxFontDelegate::instance(); |
127 if (delegate) | 167 if (delegate) |
128 params = delegate->GetDefaultFontRenderParams(); | 168 params = delegate->GetDefaultFontRenderParams(); |
129 QueryFontconfig(query, ¶ms, family_out); | 169 QueryFontconfig(query, ¶ms, family_out); |
130 | 170 |
131 if (!params.antialiasing) { | 171 if (!params.antialiasing) { |
132 // Cairo forces full hinting when antialiasing is disabled, since anything | 172 // Cairo forces full hinting when antialiasing is disabled, since anything |
(...skipping 12 matching lines...) Expand all Loading... |
145 | 185 |
146 // To enable subpixel positioning, we need to disable hinting. | 186 // To enable subpixel positioning, we need to disable hinting. |
147 if (params.subpixel_positioning) | 187 if (params.subpixel_positioning) |
148 params.hinting = FontRenderParams::HINTING_NONE; | 188 params.hinting = FontRenderParams::HINTING_NONE; |
149 } | 189 } |
150 | 190 |
151 // Use the first family from the list if Fontconfig didn't suggest a family. | 191 // Use the first family from the list if Fontconfig didn't suggest a family. |
152 if (family_out && family_out->empty() && !query.families.empty()) | 192 if (family_out && family_out->empty() && !query.families.empty()) |
153 *family_out = query.families[0]; | 193 *family_out = query.families[0]; |
154 | 194 |
| 195 cache.Put(hash, params); |
155 return params; | 196 return params; |
156 } | 197 } |
157 | 198 |
| 199 void ClearFontRenderParamsCacheForTest() { |
| 200 g_clear_cache_for_test = true; |
| 201 } |
| 202 |
158 } // namespace gfx | 203 } // namespace gfx |
OLD | NEW |