#include "graphics/FontTexture.h" #include #include #include "graphics/Image.h" #include "graphics/Texture.h" #include "graphics/TextureManager.h" #include "utilities/IOUtilities.h" #include "utilities/JSONParser.h" FontTexture * FontTexture_create() { FontTexture * self; self = malloc(sizeof(FontTexture)); FontTexture_init(self); return self; } void FontTexture_init(FontTexture * self) { int charIndex; self->texture = NULL; self->emHeight = 0; for (charIndex = 0; charIndex < 95; charIndex++) { self->characters[charIndex].textureLeft = 0.0f; self->characters[charIndex].textureRight = 0.0f; self->characters[charIndex].textureBottom = 0.0f; self->characters[charIndex].textureTop = 0.0f; self->characters[charIndex].advancement = 0.0f; self->characters[charIndex].kerningTable.numberOfEntries = 0; self->characters[charIndex].kerningTable.entries = NULL; } } void FontTexture_readProperties(FontTexture * self, const char * filePath) { JSONNode * fontProperties = NULL; fontProperties = jsonFromFile(filePath); if (fontProperties != NULL) { // TODO: Validation size_t propertyIndex; for (propertyIndex = 0; propertyIndex < fontProperties->numberOfChildren; propertyIndex++) { if (!strcmp("texture", fontProperties->children[propertyIndex].key)) { self->texture = TextureManager_getTexture(fontProperties->children[propertyIndex].value.string); } else if (!strcmp("em_height", fontProperties->children[propertyIndex].key)) { self->emHeight = fontProperties->children[propertyIndex].value.number; } else if (!strcmp("character_dimensions", fontProperties->children[propertyIndex].key)) { unsigned int characterIndex; for (characterIndex = 0; characterIndex < fontProperties->children[propertyIndex].numberOfChildren; characterIndex++) { if (fontProperties->children[propertyIndex].children[characterIndex].key[0] >= ' ' && fontProperties->children[propertyIndex].children[characterIndex].key[0] <= '~') { unsigned int dimensionsPropertyIndex; unsigned int characterDimensionsIndex; characterDimensionsIndex = fontProperties->children[propertyIndex].children[characterIndex].key[0] - ' '; for (dimensionsPropertyIndex = 0; dimensionsPropertyIndex < fontProperties->children[propertyIndex].children[characterIndex].numberOfChildren; dimensionsPropertyIndex++) { if (!strcmp("offset", fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].key)) { self->characters[characterDimensionsIndex].offset = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].value.number; } else if (!strcmp("advancement", fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].key)) { self->characters[characterDimensionsIndex].advancement = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].value.number; } else if (!strcmp("texture_bounds", fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].key)) { self->characters[characterDimensionsIndex].textureLeft = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].children[0].value.number; self->characters[characterDimensionsIndex].textureRight = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].children[1].value.number; self->characters[characterDimensionsIndex].textureBottom = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].children[2].value.number; self->characters[characterDimensionsIndex].textureTop = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].children[3].value.number; } else if (!strcmp("kerning_table", fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].key)) { unsigned int entryIndex; self->characters[characterDimensionsIndex].kerningTable.numberOfEntries = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].numberOfChildren; free(self->characters[characterDimensionsIndex].kerningTable.entries); self->characters[characterDimensionsIndex].kerningTable.entries = malloc(sizeof(struct FontTexture_kerningTableEntry) * self->characters[characterDimensionsIndex].kerningTable.numberOfEntries); for (entryIndex = 0; entryIndex < self->characters[characterDimensionsIndex].kerningTable.numberOfEntries; entryIndex++) { self->characters[characterDimensionsIndex].kerningTable.entries[entryIndex].previous = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].children[entryIndex].key[0]; self->characters[characterDimensionsIndex].kerningTable.entries[entryIndex].offset = fontProperties->children[propertyIndex].children[characterIndex].children[dimensionsPropertyIndex].children[entryIndex].value.number; } } } } } } } JSONParser_freeNodeContents(fontProperties); free(fontProperties); } if (self->texture != NULL && self->texture->image != NULL) { int charIndex; float imageWidth, imageHeight; unsigned int entryIndex; imageWidth = self->texture->image->width; imageHeight = self->texture->image->height; for (charIndex = 0; charIndex < 95; charIndex++) { self->characters[charIndex].offset /= (self->characters[charIndex].textureTop - self->characters[charIndex].textureBottom); self->characters[charIndex].advancement /= (self->characters[charIndex].textureTop - self->characters[charIndex].textureBottom); for (entryIndex = 0; entryIndex < self->characters[charIndex].kerningTable.numberOfEntries; entryIndex++) { self->characters[charIndex].kerningTable.entries[entryIndex].offset /= (self->characters[charIndex].textureTop - self->characters[charIndex].textureBottom); } self->characters[charIndex].textureLeft /= imageWidth; self->characters[charIndex].textureRight /= imageWidth; self->characters[charIndex].textureBottom /= imageHeight; self->characters[charIndex].textureTop /= imageHeight; } } } void FontTexture_dispose(FontTexture * self) { int charIndex; for (charIndex = 0; charIndex < 95; charIndex++) { free(self->characters[charIndex].kerningTable.entries); } free(self); }