1// Copyright 2014 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
5#include "ui/gfx/font_fallback.h"
6
7#include <fontconfig/fontconfig.h>
8
9#include <map>
10#include <string>
11#include <vector>
12
13#include "base/lazy_instance.h"
14
15namespace gfx {
16
17namespace {
18
19typedef std::map<std::string, std::vector<std::string> > FallbackCache;
20base::LazyInstance<FallbackCache>::Leaky g_fallback_cache =
21    LAZY_INSTANCE_INITIALIZER;
22
23}  // namespace
24
25std::vector<std::string> GetFallbackFontFamilies(
26    const std::string& font_family) {
27  std::vector<std::string>* fallback_fonts =
28      &g_fallback_cache.Get()[font_family];
29  if (!fallback_fonts->empty())
30    return *fallback_fonts;
31
32  FcPattern* pattern = FcPatternCreate();
33  FcValue family;
34  family.type = FcTypeString;
35  family.u.s = reinterpret_cast<const FcChar8*>(font_family.c_str());
36  FcPatternAdd(pattern, FC_FAMILY, family, FcFalse);
37  if (FcConfigSubstitute(NULL, pattern, FcMatchPattern) == FcTrue) {
38    FcDefaultSubstitute(pattern);
39    FcResult result;
40    FcFontSet* fonts = FcFontSort(NULL, pattern, FcTrue, NULL, &result);
41    if (fonts) {
42      for (int i = 0; i < fonts->nfont; ++i) {
43        char* name = NULL;
44        FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0,
45            reinterpret_cast<FcChar8**>(&name));
46        // FontConfig returns multiple fonts with the same family name and
47        // different configurations. Check to prevent duplicate family names.
48        if (fallback_fonts->empty() || fallback_fonts->back() != name)
49          fallback_fonts->push_back(std::string(name));
50      }
51      FcFontSetDestroy(fonts);
52    }
53  }
54  FcPatternDestroy(pattern);
55
56  if (fallback_fonts->empty())
57    fallback_fonts->push_back(font_family);
58
59  return *fallback_fonts;
60}
61
62}  // namespace gfx
63