1 /** @file fontmanifest.cpp Font resource manifest.
2 *
3 * @authors Copyright © 2003-2017 Jaakko Keränen <jaakko.keranen@iki.fi>
4 * @authors Copyright © 2005-2013 Daniel Swanson <danij@dengine.net>
5 *
6 * @par License
7 * GPL: http://www.gnu.org/licenses/gpl.html
8 *
9 * <small>This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version. This program is distributed in the hope that it
13 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 * Public License for more details. You should have received a copy of the GNU
16 * General Public License along with this program; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA</small>
19 */
20
21 #include "de_platform.h"
22 #include "resource/fontmanifest.h"
23
24 #include "dd_main.h" // App_Fonts(), remove me
25 #include "FontScheme"
26 #include <de/Log>
27
28 using namespace de;
29
DENG2_PIMPL(FontManifest)30 DENG2_PIMPL(FontManifest),
31 DENG2_OBSERVES(AbstractFont, Deletion)
32 {
33 int uniqueId;
34 QScopedPointer<AbstractFont>(resource); ///< Associated resource (if any).
35
36 Impl(Public *i)
37 : Base(i)
38 , uniqueId(0)
39 {}
40
41 ~Impl()
42 {
43 DENG2_FOR_PUBLIC_AUDIENCE(Deletion, i) i->fontManifestBeingDeleted(self());
44 }
45
46 // Observes AbstractFont::Deletion.
47 void fontBeingDeleted(AbstractFont const & /*resource*/)
48 {
49 resource.reset();
50 }
51 };
52
FontManifest(PathTree::NodeArgs const & args)53 FontManifest::FontManifest(PathTree::NodeArgs const &args)
54 : Node(args), d(new Impl(this))
55 {}
56
scheme() const57 FontScheme &FontManifest::scheme() const
58 {
59 LOG_AS("FontManifest");
60 /// @todo Optimize: FontManifest should contain a link to the owning FontScheme.
61 foreach(FontScheme *scheme, App_Resources().allFontSchemes())
62 {
63 if(&scheme->index() == &tree()) return *scheme;
64 }
65 /// @throw Error Failed to determine the scheme of the manifest (should never happen...).
66 throw Error("FontManifest::scheme", String("Failed to determine scheme for manifest [%1]").arg(de::dintptr(this)));
67 }
68
schemeName() const69 String const &FontManifest::schemeName() const
70 {
71 return scheme().name();
72 }
73
description(de::Uri::ComposeAsTextFlags uriCompositionFlags) const74 String FontManifest::description(de::Uri::ComposeAsTextFlags uriCompositionFlags) const
75 {
76 return String("%1").arg(composeUri().compose(uriCompositionFlags | Uri::DecodePath),
77 ( uriCompositionFlags.testFlag(Uri::OmitScheme)? -14 : -22 ) );
78 }
79
uniqueId() const80 int FontManifest::uniqueId() const
81 {
82 return d->uniqueId;
83 }
84
setUniqueId(int newUniqueId)85 bool FontManifest::setUniqueId(int newUniqueId)
86 {
87 LOG_AS("FontManifest");
88
89 if(d->uniqueId == newUniqueId) return false;
90
91 d->uniqueId = newUniqueId;
92
93 // Notify interested parties that the uniqueId has changed.
94 DENG2_FOR_AUDIENCE(UniqueIdChange, i) i->fontManifestUniqueIdChanged(*this);
95
96 return true;
97 }
98
hasResource() const99 bool FontManifest::hasResource() const
100 {
101 return !d->resource.isNull();
102 }
103
resource() const104 AbstractFont &FontManifest::resource() const
105 {
106 if(hasResource())
107 {
108 return *d->resource.data();
109 }
110 /// @throw MissingFontError No resource is associated with the manifest.
111 throw MissingFontError("FontManifest::resource", "No resource is associated");
112 }
113
setResource(AbstractFont * newResource)114 void FontManifest::setResource(AbstractFont *newResource)
115 {
116 LOG_AS("FontManifest");
117
118 if(d->resource.data() != newResource)
119 {
120 if(AbstractFont *curFont = d->resource.data())
121 {
122 // Cancel notifications about the existing resource.
123 curFont->audienceForDeletion -= d;
124 }
125
126 d->resource.reset(newResource);
127
128 if(AbstractFont *curFont = d->resource.data())
129 {
130 // We want notification when the new resource is about to be deleted.
131 curFont->audienceForDeletion += d;
132 }
133 }
134 }
135