Rose
Font.h
Go to the documentation of this file.
1 
8 /*
9  Another significant redesign to update the coding standards to C++17,
10  reduce the amount of bare pointer handling (especially in user code),
11  and focus on the RaspberryPi environment.
12 
13  License terms for the changes as well as the base nanogui-sdl code are
14  contained int the LICENSE.txt file.
15 
16  A significant redesign of this code was contributed by Christian Schueller.
17 
18  Based on NanoGUI by Wenzel Jakob <wenzel@inf.ethz.ch>.
19  Adaptation for SDL by Dalerank <dalerankn8@gmail.com>
20 
21  All rights reserved. Use of this source code is governed by a
22  BSD-style license that can be found in the LICENSE.txt file.
23 */
24 
25 #pragma once
26 
27 #include <filesystem>
28 #include <optional>
29 #include <memory>
30 #include <SDL2/SDL_ttf.h>
31 #include <iostream>
32 #include <map>
33 #include <vector>
34 //#include "Theme.h"
35 #include "Utilities.h"
36 
37 namespace rose {
38 
43  class FontDestroy {
44  public:
49  void operator()(TTF_Font *ttfFont) {
50  TTF_CloseFont(ttfFont);
51  }
52  };
53 
54  using FontPointer = std::shared_ptr<TTF_Font>;
55  using FontCacheKey = std::pair<std::string, int>;
56  using FontCacheStore = std::map<FontCacheKey, FontPointer>;
57 
64  inline auto textSizeUTF8(FontPointer &fontPointer, const std::string &text) {
65  int w, h;
66  TTF_SizeUTF8(fontPointer.get(), text.c_str(), &w, &h);
67  return std::make_tuple(w, h);
68  }
69 
74  class FontCache {
75  protected:
76  std::vector<std::filesystem::path> mFontPathList{};
77 
78  FontCache() {
79  std::stringstream strm("/usr/share/fonts:/usr/local/share/fonts");
80  std::string rootPathStr{};
81  while (getline(strm, rootPathStr, ':')) {
82  mFontPathList.emplace_back(rootPathStr);
83  }
84  }
85 
86  public:
87  static FontCache& getFontCache() {
88  static FontCache instance{};
89 
90  return instance;
91  }
92 
100  template<typename StringType>
101  std::optional<std::filesystem::path> locateFont(const std::filesystem::path &path, StringType fontName) {
102  for (auto &p : std::filesystem::recursive_directory_iterator(path)) {
103  if (p.path().stem() == fontName && p.is_regular_file()) {
104  return p.path();
105  }
106  }
107  return std::nullopt;
108  }
109 
116  template<typename StringType>
117  std::optional<std::filesystem::path> getFontPath(StringType fontName) {
118  if (auto found = mFontPathMap.find(fontName); found != mFontPathMap.end())
119  return found->second;
120 
121  for (auto const &rootPath : mFontPathList) {
122  auto fontPath = locateFont(rootPath, fontName);
123  if (fontPath) {
124  mFontPathMap[fontName] = fontPath.value();
125  return fontPath;
126  }
127  }
128 
129  return std::nullopt;
130  }
131 
139  template<typename StringType>
140  FontPointer getFont(StringType fontName, int ptSize) {
141  if (auto found = mFontCache.find(FontCacheKey{fontName, ptSize}); found != mFontCache.end()) {
142  return found->second;
143  }
144 
145  if (auto fontPath = getFontPath(fontName); fontPath) {
146  FontPointer fontPointer{TTF_OpenFont(fontPath.value().c_str(), ptSize), FontDestroy{}};
147  auto font = mFontCache.emplace(FontCacheKey{fontName, ptSize}, fontPointer);
148  if (font.second) {
149  return font.first->second;
150  }
151  }
152 
153  return nullptr;
154  }
155 
156  protected:
157  std::map<std::string, std::filesystem::path> mFontPathMap;
158 
159  std::map<FontCacheKey, FontPointer> mFontCache;
160  };
161 
162  inline std::tuple<int, int, int, int, int> getGlyphMetrics(FontPointer &font, char glyph) {
163  int minx{}, maxx{}, miny{}, maxy{}, advance{};
164  if (font)
165  TTF_GlyphMetrics(font.get(), glyph, &minx, &maxx, &miny, &maxy, &advance);
166  return std::make_tuple(minx, maxx, miny, maxy, advance);
167  }
168 
173  struct FontMetrics {
174  int fontAscent,
175  fontDescent,
176  fontHeight,
177  fontLineSkip;
178 
179  constexpr FontMetrics(const FontMetrics &) noexcept = default;
180  constexpr FontMetrics(FontMetrics &&) noexcept = default;
181  constexpr FontMetrics& operator=(const FontMetrics &) noexcept = default;
182  constexpr FontMetrics& operator=(FontMetrics &&) noexcept = default;
183  };
184 
191  inline auto getFontMetrics(FontPointer &font) {
192  FontMetrics fontMetrics{};
193  fontMetrics.fontHeight = TTF_FontHeight(font.get());
194  fontMetrics.fontAscent = TTF_FontAscent(font.get());
195  fontMetrics.fontDescent = TTF_FontDescent(font.get());
196  fontMetrics.fontLineSkip = TTF_FontLineSkip(font.get());
197  return fontMetrics;
198  }
199 
209  inline auto fetchFont(FontCache &fontCache, const std::string &fontName, int fontSize) {
210  auto font = fontCache.getFont(fontName, fontSize);
211  if (!font) {
212  font = fontCache.getFont("FreeSans", fontSize);
213  if (!font)
214  throw std::runtime_error(StringCompositor("Neither font", fontName, " nor default font 'FreeSans' found: ",
215  FILE_LOC));
216  }
217  return font;
218  }
219 }
std::map< FontCacheKey, FontPointer > mFontCache
The font cache.
Definition: Font.h:159
std::optional< std::filesystem::path > getFontPath(StringType fontName)
Find a font name in the font name cache.
Definition: Font.h:117
void operator()(TTF_Font *ttfFont)
Destroy a TTF_Font pointer.
Definition: Font.h:49
std::string StringCompositor(Arg &&arg, Args &&... args)
Composite a pack of arguments that are streamable to a string.
Definition: Utilities.h:114
std::pair< std::string, int > FontCacheKey
Type for TTF cache key.
Definition: Font.h:55
std::shared_ptr< TTF_Font > FontPointer
Type for TTF smart pointer.
Definition: Font.h:54
std::map< FontCacheKey, FontPointer > FontCacheStore
Type for TTF cache store.
Definition: Font.h:56
int fontLineSkip
The size of a line advance for the font.
Definition: Font.h:174
auto fetchFont(FontCache &fontCache, const std::string &fontName, int fontSize)
Fetch a font.
Definition: Font.h:209
auto textSizeUTF8(FontPointer &fontPointer, const std::string &text)
Get the size of a UTF8 string.
Definition: Font.h:64
std::optional< std::filesystem::path > locateFont(const std::filesystem::path &path, StringType fontName)
Locate a font file.
Definition: Font.h:101
FontPointer getFont(StringType fontName, int ptSize)
Get a FontPointer to a named Font of a specific point size.
Definition: Font.h:140
auto getFontMetrics(FontPointer &font)
Get the font metrics of the current font.
Definition: Font.h:191
The size metrics that pertain to a particular font.
Definition: Font.h:173
Cache storage for requested fonts.
Definition: Font.h:74
ToDo: There is an issue that the initial scroll interaction is lost if the click/press lands on a Wid...
Definition: CelestialOverlay.cpp:13
std::map< std::string, std::filesystem::path > mFontPathMap
The font file path cache.
Definition: Font.h:157
A functor to destroy a TTF_Font.
Definition: Font.h:43
int fontHeight
The total height of the font (ascent - descent.
Definition: Font.h:174