Cogs.Core
FontManager.cpp
1#include "FontManager.h"
2
3#include "Foundation/Logging/Logger.h"
4
5#include "ResourceStore.h"
6
7#include "Context.h"
8
9#include "TextureManager.h"
10
11#include "Services/TaskManager.h"
12
13#include <cmath>
14
15namespace
16{
17 Cogs::Logging::Log logger = Cogs::Logging::getLogger("FontManager");
18}
19
21{
22 reportLeaks("Font");
23}
24
26{
27 ResourceManager::initialize();
28
29 DefaultMonospaceFont = getNextResourceId();
30 DefaultRegularFont = getNextResourceId();
31 DefaultBoldFont = getNextResourceId();
32
33 defaultResource = loadFont("Fonts/Inconsolata-Regular.ttf", 16, DefaultMonospaceFont);
34 regularFont = loadFont("Fonts/SourceSansPro-Regular.ttf", 20, DefaultRegularFont);
35 boldFont = loadFont("Fonts/SourceCodePro-Bold.ttf", 36, DefaultBoldFont);
36
37#ifdef _WIN32
38 context->resourceStore->addSearchPath("C:/Windows/Fonts/");
39#endif
40
41 LOG_DEBUG(logger, "Initialized font manager.");
42}
43
45{
46 defaultResource = FontHandle::NoHandle;
47 boldFont = FontHandle::NoHandle;
48 regularFont = FontHandle::NoHandle;
49
50 sharedFonts.clear();
51 swapQueue.clear();
52
54}
55
56Cogs::Core::FontHandle Cogs::Core::FontManager::loadFont(const std::string & name, float size, const ResourceId id, ResourceLoadFlags flags)
57{
58 return loadFont(FontDefinition{ .fontFamily = name, .fontSize = size }, id, flags);
59}
60
62{
63 auto sharedFont = sharedFonts.find(definition);
64
65 // Reuse existing if handle is accessible by client, e.g. not released.
66 if (sharedFont != sharedFonts.end() && isValidResource(sharedFont->second->getId())) {
67 return sharedFont->second;
68 }
69
70 if (resourceId == NoResourceId) {
71 resourceId = getNextResourceId();
72 }
73
74 // Font not matching any existing fonts. Avoid reusing resource with same path, but different size.
75 FontLoadInfo & loadInfo = *createLoadInfo();
76 loadInfo.resourceId = resourceId;
77 loadInfo.loadFlags = flags;
78
79 //FIXME: Make font path lookup platform independent.
80 loadInfo.definition = definition;
81 loadInfo.resourceName = definition.fontFamily + " " + std::to_string(definition.fontSize) + "px";
82#ifdef _WIN32
83 if (definition.fontFamily.find("System:") != std::string::npos) {
84 loadInfo.resourcePath = "C:/Windows/Fonts/" + definition.fontFamily.substr(7) + ".ttf";
85 } else {
86 loadInfo.resourcePath = definition.fontFamily;
87 }
88#else
89 loadInfo.resourcePath = definition.fontFamily;
90#endif
91
92 auto handle = loadResource(&loadInfo);
93
94 // Default fonts (and corresponding texture, see handleActivation()) as dependency resources to
95 // ensure the scene is redrawn when ready.
96 handle->setFlag(ResourceFlags::Dependency);
97
98 sharedFonts[definition] = handle;
99
100 return handle;
101}
102
104{
105 if (!checkPreloaded(loadInfo)) return;
106
107 auto loadResource = [loadInfo, this]()
108 {
109 auto loader = findLoader(loadInfo);
110
111 if (loader) {
112 if (!loader->load(context, *loadInfo)) {
113 loadInfo->handle->setFailedLoad();
114 }
115 } else {
116 LOG_WARNING(logger, "No suitable font loader found for %s.", loadInfo->resourceName.c_str());
117
118 loadInfo->handle->setFailedLoad();
119 }
120
121 setProcessed(loadInfo, !loadInfo->loadSync());
122 };
123
124 if (loadInfo->loadSync()) {
125 loadResource();
126 } else {
127 context->taskManager->enqueue(TaskManager::ResourceQueue, loadResource);
128 }
129}
130
131namespace Cogs
132{
133 namespace Core
134 {
135 inline void getCharacterQuad(const Font::Character * chardata, int pw, int ph, int charIndex, float * xPos, float * yPos, Font::BakedCharacter * q, int openGLFill, int alignToInteger = 0)
136 {
137 const float d3dBias = openGLFill ? 0 : -0.5f;
138 float ipw = 1.0f / pw, iph = 1.0f / ph;
139 const Font::Character * b = chardata + charIndex;
140
141 if (alignToInteger) {
142 float x = floorf((*xPos + b->xOffset) + 0.5f);
143 float y = floorf((*yPos + b->yOffset) + 0.5f);
144 q->x0 = x + d3dBias;
145 q->y0 = y + d3dBias;
146 q->x1 = x + b->xOffset2 - b->xOffset + d3dBias;
147 q->y1 = y + b->yOffset2 - b->yOffset + d3dBias;
148 } else {
149 q->x0 = *xPos + b->xOffset + d3dBias;
150 q->y0 = *yPos + b->yOffset + d3dBias;
151 q->x1 = *xPos + b->xOffset2 + d3dBias;
152 q->y1 = *yPos + b->yOffset2 + d3dBias;
153 }
154
155 q->s0 = b->x0 * ipw;
156 q->t0 = b->y0 * iph;
157 q->s1 = b->x1 * ipw;
158 q->t1 = b->y1 * iph;
159
160 *xPos += b->xAdvance;
161 }
162 }
163}
164
165void Cogs::Core::FontManager::getBakedCharacter(const Font * font, int characterIndex, float & x, float & y, Font::BakedCharacter & bakedCharacter) const
166{
167 if (characterIndex < 0) {
168 characterIndex += 256;
169 } else if (characterIndex > 255) {
170 characterIndex = 0;
171 }
172
173 getCharacterQuad(font->characters.data(), font->bitmapSize, font->bitmapSize, characterIndex, &x, &y, &bakedCharacter, true, true);
174}
175
177{
178 LOG_WARNING(logger, "Loading font from path %s failed.", loadInfo->resourcePath.c_str());
179}
180
182{
183 auto textureManager = context->textureManager;
184
185 if (font->bitmap.empty()) {
186 LOG_ERROR(logger, "Font contents empty.");
188 }
189
190 auto texture = textureManager->loadTexture2D(font->bitmap.data(),
191 font->bitmapSize,
192 font->bitmapSize,
193 TextureFormat::R8G8B8A8_UNORM_SRGB,
194 0,
195 NoResourceId,
197
198 if (HandleIsValid(texture)) {
199 font->texture = texture;
200
201 texture->setName("Texture:" + font->getName().to_string());
202 texture->setFlag(ResourceFlags::Dependency);
203
205 } else {
207 }
208}
209
211{
212 font->unsetFlag(ResourceFlags::Resident);
213}
ActivationResult handleActivation(FontHandle handle, Font *font) override
Overridden to activate loaded font resources, triggering loading of the font Texture.
void handleDeletion(Font *font) override
Handler for deletion of resources.
~FontManager() override
Destructs the FontManaer.
Definition: FontManager.cpp:20
void clear() override
Clear the FontManager, releasing all default Font resources.
Definition: FontManager.cpp:44
void getBakedCharacter(const Font *font, int characterIndex, float &x, float &y, Font::BakedCharacter &bakedCharacter) const
Retrieve baked character information for rendering.
void handleLoad(FontLoadInfo *loadInfo) override
Overridden to load Font resources.
void handleFailedLoad(const FontLoadInfo *loadInfo) override
Handle failed Font loads, logging and cleaning up.
void initialize() override
Initialize the FontManager, creating default Font resources.
Definition: FontManager.cpp:25
COGSCORE_DLL_API FontHandle loadFont(const std::string &name, float size, ResourceId resourceId, ResourceLoadFlags flags=ResourceLoadFlags::None)
Load a Font resource from the file resource with the given name.
Definition: FontManager.cpp:56
void clear() override
Clear the resource manager, cleaning up resources held by member handles.
static constexpr TaskQueueId ResourceQueue
Resource task queue.
Definition: TaskManager.h:232
Log implementation class.
Definition: LogManager.h:139
@ Dependency
The resource is a dependency that should trigger subsequent updates if changed.
@ Resident
The resource is loaded onto the GPU.
ActivationResult
Defines results for resource activation.
Definition: ResourceBase.h:14
@ Success
Resource activated successfully.
@ Failure
Resource activation failed.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
ResourceLoadFlags
Flags for describing how to load a resource.
Definition: ResourceFlags.h:16
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:180
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
Defines a Font.
Definition: Font.h:91
std::string fontFamily
Font family name, such as "Arial" or "Tahoma".
Definition: Font.h:93
float fontSize
Size of the font in pixels.
Definition: Font.h:96
Defines information used to load a Font resource.
Definition: IFontLoader.h:17
FontDefinition definition
Definition of the Font resource.
Definition: IFontLoader.h:19
Defines a quad with locations in screen space defined by [x0, y0] and [x1, y1].
Definition: Font.h:48
Defines a single character from a font resource.
Definition: Font.h:29
Font resources are used to render text with a specific font and size.
Definition: Font.h:22
static const ResourceHandle_t NoHandle
Handle representing a default (or none if default not present) resource.
std::string resourcePath
Resource path. Used to locate resource.
std::string resourceName
Desired resource name. If no name is given, a default name will be chosen.
ResourceId resourceId
Unique resource identifier. Must be unique among resources of the same kind.
ResourceHandleBase handle
Handle to resource structure for holding actual resource data.
ResourceLoadFlags loadFlags
Desired loading flags. Used to specify how the resource will be loaded.