1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef MINIKIN_SYSTEM_FONTS_H
18 #define MINIKIN_SYSTEM_FONTS_H
19 
20 #include <map>
21 #include <memory>
22 #include <mutex>
23 #include <string>
24 
25 #include "minikin/FontCollection.h"
26 #include "minikin/U16StringPiece.h"
27 
28 namespace minikin {
29 
30 // Provides a system font mapping.
31 class SystemFonts {
32 public:
findFontCollection(const std::string & familyName)33     static std::shared_ptr<FontCollection> findFontCollection(const std::string& familyName) {
34         return getInstance().findFontCollectionInternal(familyName);
35     }
36 
registerFallback(const std::string & familyName,const std::shared_ptr<FontCollection> & fc)37     static void registerFallback(const std::string& familyName,
38                                  const std::shared_ptr<FontCollection>& fc) {
39         return getInstance().registerFallbackInternal(familyName, fc);
40     }
41 
registerDefault(const std::shared_ptr<FontCollection> & fc)42     static void registerDefault(const std::shared_ptr<FontCollection>& fc) {
43         return getInstance().registerDefaultInternal(fc);
44     }
45 
46     using FontMapDeleter = std::function<void()>;
47 
addFontMap(std::shared_ptr<FontCollection> && collections)48     static void addFontMap(std::shared_ptr<FontCollection>&& collections) {
49         return getInstance().addFontMapInternal(std::move(collections));
50     }
51 
52     // This obtains a mutex inside, so do not call this method inside callback.
getFontMap(std::function<void (const std::vector<std::shared_ptr<FontCollection>> &)> func)53     static void getFontMap(
54             std::function<void(const std::vector<std::shared_ptr<FontCollection>>&)> func) {
55         return getInstance().getFontMapInternal(func);
56     }
57 
getFontSet(std::function<void (const std::vector<std::shared_ptr<Font>> &)> func)58     static void getFontSet(std::function<void(const std::vector<std::shared_ptr<Font>>&)> func) {
59         return getInstance().getFontSetInternal(func);
60     }
61 
62 protected:
63     // Visible for testing purposes.
SystemFonts()64     SystemFonts() {}
~SystemFonts()65     virtual ~SystemFonts() {}
66 
67     std::shared_ptr<FontCollection> findFontCollectionInternal(const std::string& familyName);
registerFallbackInternal(const std::string & familyName,const std::shared_ptr<FontCollection> & fc)68     void registerFallbackInternal(const std::string& familyName,
69                                   const std::shared_ptr<FontCollection>& fc) {
70         std::lock_guard<std::mutex> lock(mMutex);
71         mSystemFallbacks[familyName] = fc;
72     }
73 
registerDefaultInternal(const std::shared_ptr<FontCollection> & fc)74     void registerDefaultInternal(const std::shared_ptr<FontCollection>& fc) {
75         std::lock_guard<std::mutex> lock(mMutex);
76         mDefaultFallback = fc;
77     }
78 
addFontMapInternal(std::shared_ptr<FontCollection> && collections)79     void addFontMapInternal(std::shared_ptr<FontCollection>&& collections) {
80         std::lock_guard<std::mutex> lock(mMutex);
81         mCollections.emplace_back(std::move(collections));
82     }
83 
getFontMapInternal(std::function<void (const std::vector<std::shared_ptr<FontCollection>> &)> func)84     void getFontMapInternal(
85             std::function<void(const std::vector<std::shared_ptr<FontCollection>>&)> func) {
86         std::lock_guard<std::mutex> lock(mMutex);
87         func(mCollections);
88     }
89 
getFontSetInternal(std::function<void (const std::vector<std::shared_ptr<Font>> &)> func)90     void getFontSetInternal(std::function<void(const std::vector<std::shared_ptr<Font>>&)> func) {
91         std::lock_guard<std::mutex> lock(mMutex);
92         if (!mFonts) {
93             buildFontSetLocked();
94         }
95         func(mFonts.value());
96     }
97 
98 private:
99     static SystemFonts& getInstance();
100 
101     void buildFontSetLocked() EXCLUSIVE_LOCKS_REQUIRED(mMutex);
102 
103     std::map<std::string, std::shared_ptr<FontCollection>> mSystemFallbacks GUARDED_BY(mMutex);
104     std::shared_ptr<FontCollection> mDefaultFallback GUARDED_BY(mMutex);
105     std::vector<std::shared_ptr<FontCollection>> mCollections GUARDED_BY(mMutex);
106     std::optional<std::vector<std::shared_ptr<Font>>> mFonts GUARDED_BY(mMutex);
107 
108     std::mutex mMutex;
109 };
110 
111 }  // namespace minikin
112 
113 #endif  // MINIKIN_SYSTEM_FONTS_H
114