--- /dev/null
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "dcpomatic_assert.h"
+
+
+/** Comparator to allow dcpomatic::Font::Content to be compared for use in a map */
+struct FontComparator
+{
+ bool operator()(dcpomatic::Font::Content const& a, dcpomatic::Font::Content const& b) const {
+ auto const a_has_file = static_cast<bool>(a.file);
+ auto const b_has_file = static_cast<bool>(b.file);
+ auto const a_has_data = static_cast<bool>(a.data);
+ auto const b_has_data = static_cast<bool>(b.data);
+
+ if (!a_has_file && !a_has_data && !b_has_file && !b_has_data) {
+ /* Neither font has any font data: a == b */
+ return false;
+ } else if (!a_has_file && !a_has_data) {
+ /* Fonts with no data are the "lowest": a < b */
+ return true;
+ } else if (!b_has_file && !b_has_data) {
+ /* ... so here b < a */
+ return false;
+ } else if (a_has_file && !b_has_file) {
+ /* Fonts with file are lower than fonts with data: a < b */
+ return true;
+ } else if (!a_has_file && b_has_file) {
+ /* ... so here b < a */
+ return false;
+ } else if (a_has_file && b_has_file) {
+ /* Compared as "equals" */
+ return a.file->string() < b.file->string();
+ } else if (a_has_data && b_has_data) {
+ /* Compared as "equals" */
+ auto const a_size = a.data->size();
+ auto const b_size = b.data->size();
+ if (a_size != b_size) {
+ return a_size < b_size;
+ }
+ return memcmp(a.data->data(), b.data->data(), a_size) < 0;
+ }
+
+ /* Should never get here */
+ DCPOMATIC_ASSERT(false);
+ return false;
+ };
+};
+
+
string
FontConfig::make_font_available(shared_ptr<dcpomatic::Font> font)
{
- auto existing = _available_fonts.find(font->id());
+ auto existing = _available_fonts.find(font->content());
if (existing != _available_fonts.end()) {
return existing->second;
}
DCPOMATIC_ASSERT(font_name);
- _available_fonts[font->id()] = *font_name;
+ /* We need to use the font object as the key, as we may be passed the same shared_ptr to a modified
+ * Font object in the future and in that case we need to load the new font.
+ */
+ _available_fonts[font->content()] = *font_name;
FcConfigBuildFonts(_config);
return *font_name;
*/
+#include "font_comparator.h"
#include <fontconfig/fontconfig.h>
#include <boost/filesystem.hpp>
#include <map>
~FontConfig();
FcConfig* _config = nullptr;
- std::map<std::string, std::string> _available_fonts;
+ std::map<dcpomatic::Font::Content, std::string, FontComparator> _available_fonts;
std::vector<boost::filesystem::path> _temp_files;
--- /dev/null
+#include "lib/font.h"
+#include "lib/font_comparator.h"
+#include <boost/test/unit_test.hpp>
+#include <iostream>
+
+
+using std::make_shared;
+using std::map;
+using std::shared_ptr;
+using std::string;
+
+
+BOOST_AUTO_TEST_CASE(font_comparator_test)
+{
+ map<dcpomatic::Font::Content, string, FontComparator> cache;
+
+ auto font = make_shared<dcpomatic::Font>("foo");
+
+ BOOST_CHECK(cache.find(font->content()) == cache.end());
+ cache[font->content()] = "foo";
+ BOOST_CHECK(cache.find(font->content()) != cache.end());
+
+ font->set_file("test/data/Inconsolata-VF.ttf");
+ BOOST_CHECK(cache.find(font->content()) == cache.end());
+}
+
+