font_service_app.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  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.
  4. #include "components/services/font/font_service_app.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/command_line.h"
  8. #include "base/feature_list.h"
  9. #include "base/files/file.h"
  10. #include "base/files/file_path.h"
  11. #include "base/trace_event/trace_event.h"
  12. #include "build/build_config.h"
  13. #include "build/chromeos_buildflags.h"
  14. #include "components/services/font/fontconfig_matching.h"
  15. #include "mojo/public/cpp/system/platform_handle.h"
  16. #include "pdf/buildflags.h"
  17. #include "skia/ext/skia_utils_base.h"
  18. #include "ui/gfx/font_fallback_linux.h"
  19. #include "ui/gfx/font_render_params.h"
  20. #if BUILDFLAG(ENABLE_PDF)
  21. #include "components/services/font/pdf_fontconfig_matching.h" // nogncheck
  22. #endif
  23. static_assert(
  24. static_cast<uint32_t>(SkFontStyle::kUpright_Slant) ==
  25. static_cast<uint32_t>(font_service::mojom::TypefaceSlant::ROMAN),
  26. "Skia and font service flags must match");
  27. static_assert(
  28. static_cast<uint32_t>(SkFontStyle::kItalic_Slant) ==
  29. static_cast<uint32_t>(font_service::mojom::TypefaceSlant::ITALIC),
  30. "Skia and font service flags must match");
  31. static_assert(
  32. static_cast<uint32_t>(SkFontStyle::kOblique_Slant) ==
  33. static_cast<uint32_t>(font_service::mojom::TypefaceSlant::OBLIQUE),
  34. "Skia and font service flags must match");
  35. namespace {
  36. base::File GetFileForPath(const base::FilePath& path) {
  37. if (path.empty())
  38. return base::File();
  39. base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  40. LOG_IF(WARNING, !file.IsValid()) << "file not valid, path=" << path.value();
  41. return file;
  42. }
  43. int ConvertHinting(gfx::FontRenderParams::Hinting hinting) {
  44. switch (hinting) {
  45. case gfx::FontRenderParams::HINTING_NONE:
  46. return 0;
  47. case gfx::FontRenderParams::HINTING_SLIGHT:
  48. return 1;
  49. case gfx::FontRenderParams::HINTING_MEDIUM:
  50. return 2;
  51. case gfx::FontRenderParams::HINTING_FULL:
  52. return 3;
  53. }
  54. NOTREACHED() << "Unexpected hinting value " << hinting;
  55. return 0;
  56. }
  57. font_service::mojom::RenderStyleSwitch ConvertSubpixelRendering(
  58. gfx::FontRenderParams::SubpixelRendering rendering) {
  59. switch (rendering) {
  60. case gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE:
  61. return font_service::mojom::RenderStyleSwitch::OFF;
  62. case gfx::FontRenderParams::SUBPIXEL_RENDERING_RGB:
  63. case gfx::FontRenderParams::SUBPIXEL_RENDERING_BGR:
  64. case gfx::FontRenderParams::SUBPIXEL_RENDERING_VRGB:
  65. case gfx::FontRenderParams::SUBPIXEL_RENDERING_VBGR:
  66. return font_service::mojom::RenderStyleSwitch::ON;
  67. }
  68. NOTREACHED() << "Unexpected subpixel rendering value " << rendering;
  69. return font_service::mojom::RenderStyleSwitch::NO_PREFERENCE;
  70. }
  71. // The maximum number of entries to keep in the font family matching cache.
  72. constexpr int kCacheFontFamilyMaxSize = 3000;
  73. } // namespace
  74. namespace font_service {
  75. FontServiceApp::FontServiceApp() : match_cache_(kCacheFontFamilyMaxSize) {}
  76. FontServiceApp::~FontServiceApp() = default;
  77. void FontServiceApp::BindReceiver(
  78. mojo::PendingReceiver<mojom::FontService> receiver) {
  79. receivers_.Add(this, std::move(receiver));
  80. }
  81. void FontServiceApp::MatchFamilyName(const std::string& family_name,
  82. mojom::TypefaceStylePtr requested_style,
  83. MatchFamilyNameCallback callback) {
  84. TRACE_EVENT0("fonts", "FontServiceApp::MatchFamilyName");
  85. SkFontConfigInterface::FontIdentity result_identity;
  86. SkString result_family;
  87. SkFontStyle result_style;
  88. SkFontConfigInterface* fc =
  89. SkFontConfigInterface::GetSingletonDirectInterface();
  90. SkFontStyle font_style(
  91. requested_style->weight, requested_style->width,
  92. static_cast<SkFontStyle::Slant>(requested_style->slant));
  93. // Check for presence in cache.
  94. MatchCacheKey key;
  95. key.family_name = family_name;
  96. key.font_style = font_style;
  97. auto it = match_cache_.Get(key);
  98. if (it != match_cache_.end()) {
  99. std::move(callback).Run(
  100. it->second.identity ? it->second.identity.Clone() : nullptr,
  101. it->second.family_name, it->second.style.Clone());
  102. return;
  103. }
  104. const bool r =
  105. fc->matchFamilyName(family_name.data(), font_style, &result_identity,
  106. &result_family, &result_style);
  107. mojom::FontIdentityPtr identity = nullptr;
  108. mojom::TypefaceStylePtr style(mojom::TypefaceStyle::New());
  109. std::string result_family_cppstring = result_family.c_str();
  110. if (r) {
  111. // Stash away the returned path, so we can give it an ID (index)
  112. // which will later be given to us in a request to open the file.
  113. base::FilePath path(result_identity.fString.c_str());
  114. size_t index = FindOrAddPath(path);
  115. identity = mojom::FontIdentity::New();
  116. identity->id = static_cast<uint32_t>(index);
  117. identity->ttc_index = result_identity.fTTCIndex;
  118. identity->filepath = path;
  119. style->weight = result_style.weight();
  120. style->width = result_style.width();
  121. style->slant = static_cast<mojom::TypefaceSlant>(result_style.slant());
  122. } else {
  123. style->weight = SkFontStyle().weight();
  124. style->width = SkFontStyle().width();
  125. style->slant = static_cast<mojom::TypefaceSlant>(SkFontStyle().slant());
  126. }
  127. // Add to the cache.
  128. MatchCacheValue value;
  129. value.family_name = result_family_cppstring;
  130. value.identity = identity ? identity.Clone() : nullptr;
  131. value.style = style.Clone();
  132. match_cache_.Put(key, std::move(value));
  133. std::move(callback).Run(std::move(identity), result_family_cppstring,
  134. std::move(style));
  135. }
  136. void FontServiceApp::OpenStream(uint32_t id_number,
  137. OpenStreamCallback callback) {
  138. TRACE_EVENT0("fonts", "FontServiceApp::OpenStream");
  139. DCHECK_LT(id_number, static_cast<uint32_t>(paths_.size()));
  140. base::File file;
  141. if (id_number < static_cast<uint32_t>(paths_.size()))
  142. file = GetFileForPath(paths_[id_number]);
  143. std::move(callback).Run(std::move(file));
  144. }
  145. void FontServiceApp::FallbackFontForCharacter(
  146. uint32_t character,
  147. const std::string& locale,
  148. FallbackFontForCharacterCallback callback) {
  149. TRACE_EVENT0("fonts", "FontServiceApp::FallbackFontForCharacter");
  150. gfx::FallbackFontData fallback_font;
  151. if (gfx::GetFallbackFontForChar(character, locale, &fallback_font)) {
  152. size_t index = FindOrAddPath(fallback_font.filepath);
  153. mojom::FontIdentityPtr identity(mojom::FontIdentity::New());
  154. identity->id = static_cast<uint32_t>(index);
  155. identity->ttc_index = fallback_font.ttc_index;
  156. identity->filepath = fallback_font.filepath;
  157. std::move(callback).Run(std::move(identity), fallback_font.name,
  158. fallback_font.is_bold, fallback_font.is_italic);
  159. } else {
  160. std::move(callback).Run(nullptr, "", false, false);
  161. }
  162. }
  163. void FontServiceApp::FontRenderStyleForStrike(
  164. const std::string& family,
  165. uint32_t size,
  166. bool is_bold,
  167. bool is_italic,
  168. float device_scale_factor,
  169. FontRenderStyleForStrikeCallback callback) {
  170. TRACE_EVENT0("fonts", "FontServiceApp::FontRenderStyleForStrike");
  171. gfx::FontRenderParamsQuery query;
  172. query.device_scale_factor = device_scale_factor;
  173. query.families.push_back(family);
  174. query.pixel_size = size;
  175. query.style = is_italic ? gfx::Font::ITALIC : 0;
  176. query.weight = is_bold ? gfx::Font::Weight::BOLD : gfx::Font::Weight::NORMAL;
  177. const gfx::FontRenderParams params = gfx::GetFontRenderParams(query, nullptr);
  178. mojom::FontRenderStylePtr font_render_style(mojom::FontRenderStyle::New(
  179. params.use_bitmaps ? mojom::RenderStyleSwitch::ON
  180. : mojom::RenderStyleSwitch::OFF,
  181. params.autohinter ? mojom::RenderStyleSwitch::ON
  182. : mojom::RenderStyleSwitch::OFF,
  183. params.hinting != gfx::FontRenderParams::HINTING_NONE
  184. ? mojom::RenderStyleSwitch::ON
  185. : mojom::RenderStyleSwitch::OFF,
  186. ConvertHinting(params.hinting),
  187. params.antialiasing ? mojom::RenderStyleSwitch::ON
  188. : mojom::RenderStyleSwitch::OFF,
  189. ConvertSubpixelRendering(params.subpixel_rendering),
  190. params.subpixel_positioning ? mojom::RenderStyleSwitch::ON
  191. : mojom::RenderStyleSwitch::OFF));
  192. std::move(callback).Run(std::move(font_render_style));
  193. }
  194. void FontServiceApp::MatchFontByPostscriptNameOrFullFontName(
  195. const std::string& family,
  196. MatchFontByPostscriptNameOrFullFontNameCallback callback) {
  197. TRACE_EVENT0("fonts",
  198. "FontServiceApp::MatchFontByPostscriptNameOrFullFontName");
  199. absl::optional<FontConfigLocalMatching::FontConfigMatchResult> match_result =
  200. FontConfigLocalMatching::FindFontByPostscriptNameOrFullFontName(family);
  201. if (match_result) {
  202. uint32_t fontconfig_interface_id = FindOrAddPath(match_result->file_path);
  203. mojom::FontIdentityPtr font_identity(mojom::FontIdentity::New(
  204. fontconfig_interface_id, match_result->ttc_index,
  205. match_result->file_path));
  206. std::move(callback).Run(std::move(font_identity));
  207. return;
  208. }
  209. std::move(callback).Run(nullptr);
  210. }
  211. #if BUILDFLAG(ENABLE_PDF)
  212. void FontServiceApp::MatchFontWithFallback(
  213. const std::string& family,
  214. bool is_bold,
  215. bool is_italic,
  216. uint32_t charset,
  217. uint32_t fallbackFamilyType,
  218. MatchFontWithFallbackCallback callback) {
  219. TRACE_EVENT0("fonts", "FontServiceApp::MatchFontWithFallback");
  220. base::File matched_font_file;
  221. int font_file_descriptor = MatchFontFaceWithFallback(
  222. family, is_bold, is_italic, charset, fallbackFamilyType);
  223. matched_font_file = base::File(font_file_descriptor);
  224. if (!matched_font_file.IsValid())
  225. matched_font_file = base::File();
  226. std::move(callback).Run(std::move(matched_font_file));
  227. }
  228. #endif // BUILDFLAG(ENABLE_PDF)
  229. size_t FontServiceApp::FindOrAddPath(const base::FilePath& path) {
  230. TRACE_EVENT1("fonts", "FontServiceApp::FindOrAddPath", "path",
  231. path.AsUTF8Unsafe());
  232. size_t count = paths_.size();
  233. for (size_t i = 0; i < count; ++i) {
  234. if (path == paths_[i])
  235. return i;
  236. }
  237. paths_.emplace_back(path);
  238. return count;
  239. }
  240. FontServiceApp::MatchCacheValue::MatchCacheValue() = default;
  241. FontServiceApp::MatchCacheValue::~MatchCacheValue() = default;
  242. FontServiceApp::MatchCacheValue::MatchCacheValue(MatchCacheValue&&) = default;
  243. } // namespace font_service