From 3c802dd6d1451c2c8a7e188f8379738d72e907eb Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 14 Oct 2023 21:48:25 +0200 Subject: Fix DCP content font ID allocation to cope with DCPs that have multiple fonts with the same name in the same reel (#2600). Previously we had this id_for_font_in_reel() which would give an ID of N_font-ID. This means we got duplicate font IDs. Here we replace that method with FontAllocator, which gives an ID of N_font-ID for the first font and M_font-ID, where M is a number higher than the highest reel index. The idea is to support the required new IDs without breaking exisiting projects. There is some documentation of how it works in doc/design/fonts --- src/lib/font_id_allocator.h | 102 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/lib/font_id_allocator.h (limited to 'src/lib/font_id_allocator.h') diff --git a/src/lib/font_id_allocator.h b/src/lib/font_id_allocator.h new file mode 100644 index 000000000..bd99cad63 --- /dev/null +++ b/src/lib/font_id_allocator.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 2023 Carl Hetherington + + 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 . + +*/ + + +#ifndef DCPOMATIC_FONT_ID_ALLOCATOR_H +#define DCPOMATIC_FONT_ID_ALLOCATOR_H + + +#include +#include +#include +#include + + +namespace dcp { + class Reel; + class SubtitleAsset; +} + + +/** A class which, given some pairs of (asset-id, font-id) can return a font ID + * which is unique in a piece of content. + * + * When we examine a 2-reel DCP we may have a pair of subtitle assets that + * each have a font with ID "foo". We want to store these in + * TextContent::_fonts in such a way that they are distinguishable. + * + * If TextContent is to carry on storing a list of dcpomatic::Font, we can + * only do this by making each dcpomatic::Font have a different ID (i.e. not + * both "foo"). + * + * Hence when we add the fonts to the TextContent we re-write them to have + * unique IDs. + * + * When we do this, we must do it in a repeatable way so that when the + * DCPDecoder receives the "foo" font IDs it can obtain the same "new" ID given + * "foo" and the asset ID that it came from. + * + * FontIDAllocator can help with that: call add_fonts_from_reels() or add_font(), + * then allocate(), then it will return repeatable unique "new" font IDs from + * an asset map and "old" ID. + */ +class FontIDAllocator +{ +public: + void add_fonts_from_reels(std::vector> const& reels); + void add_font(int reel_index, std::string asset_id, std::string font_id); + + void allocate(); + + std::string font_id(int reel_index, std::string asset_id, std::string font_id) const; + +private: + void add_fonts_from_asset(int reel_index, std::shared_ptr asset); + + struct Font + { + Font(int reel_index_, std::string asset_id_, std::string font_id_) + : reel_index(reel_index_) + , asset_id(asset_id_) + , font_id(font_id_) + {} + + bool operator<(Font const& other) const { + if (reel_index != other.reel_index) { + return reel_index < other.reel_index; + } + + if (asset_id != other.asset_id) { + return asset_id < other.asset_id; + } + + return font_id < other.font_id; + } + + int reel_index; + std::string asset_id; + std::string font_id; + }; + + std::map _map; +}; + + +#endif -- cgit v1.2.3