From 8aa672503985f62a40b95bed2911de14c16a862f Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 29 Dec 2016 02:45:27 -0400 Subject: [PATCH] Cleaned up some duplicated pixel format-related code in Font files. --HG-- branch : minor --- src/common/pixelformat.cpp | 3 ++ src/common/pixelformat.h | 2 + src/modules/font/BMFontRasterizer.cpp | 11 ++-- src/modules/font/BMFontRasterizer.h | 1 + src/modules/font/GlyphData.cpp | 34 +++--------- src/modules/font/GlyphData.h | 20 ++----- src/modules/font/ImageRasterizer.cpp | 7 ++- src/modules/font/ImageRasterizer.h | 10 ++-- src/modules/font/Rasterizer.h | 8 +++ .../font/freetype/TrueTypeRasterizer.cpp | 7 ++- .../font/freetype/TrueTypeRasterizer.h | 11 ++-- src/modules/font/wrap_GlyphData.cpp | 2 +- src/modules/graphics/opengl/Font.cpp | 52 ++++++------------- src/modules/graphics/opengl/Font.h | 11 +--- src/modules/graphics/opengl/OpenGL.cpp | 14 ++++- 15 files changed, 88 insertions(+), 105 deletions(-) diff --git a/src/common/pixelformat.cpp b/src/common/pixelformat.cpp index 333b451f8..3fe2b5aaf 100644 --- a/src/common/pixelformat.cpp +++ b/src/common/pixelformat.cpp @@ -45,6 +45,8 @@ static StringMap::Entry formatEntries[] = { "rg32f", PIXELFORMAT_RG32F }, { "rgba32f", PIXELFORMAT_RGBA32F }, + { "la8", PIXELFORMAT_LA8 }, + { "rgba4", PIXELFORMAT_RGBA4 }, { "rgb5a1", PIXELFORMAT_RGB5A1 }, { "rgb565", PIXELFORMAT_RGB565 }, @@ -119,6 +121,7 @@ size_t getPixelFormatSize(PixelFormat format) case PIXELFORMAT_RG8: case PIXELFORMAT_R16: case PIXELFORMAT_R16F: + case PIXELFORMAT_LA8: case PIXELFORMAT_RGBA4: case PIXELFORMAT_RGB5A1: case PIXELFORMAT_RGB565: diff --git a/src/common/pixelformat.h b/src/common/pixelformat.h index 1faf1ec7b..bf21ecc1e 100644 --- a/src/common/pixelformat.h +++ b/src/common/pixelformat.h @@ -48,6 +48,8 @@ enum PixelFormat PIXELFORMAT_RG32F, PIXELFORMAT_RGBA32F, + PIXELFORMAT_LA8, // Same as RG8, but accessed as (L, L, L, A) + // packed formats PIXELFORMAT_RGBA4, PIXELFORMAT_RGB5A1, diff --git a/src/modules/font/BMFontRasterizer.cpp b/src/modules/font/BMFontRasterizer.cpp index bb9a22b90..2cb50d5f7 100644 --- a/src/modules/font/BMFontRasterizer.cpp +++ b/src/modules/font/BMFontRasterizer.cpp @@ -291,17 +291,17 @@ GlyphData *BMFontRasterizer::getGlyphData(uint32 glyph) const // Return an empty GlyphData if we don't have the glyph character. if (it == characters.end()) - return new GlyphData(glyph, GlyphMetrics(), GlyphData::FORMAT_RGBA); + return new GlyphData(glyph, GlyphMetrics(), PIXELFORMAT_RGBA8); const BMFontCharacter &c = it->second; - GlyphData *g = new GlyphData(glyph, c.metrics, GlyphData::FORMAT_RGBA); + GlyphData *g = new GlyphData(glyph, c.metrics, PIXELFORMAT_RGBA8); const auto &imagepair = images.find(c.page); if (imagepair == images.end()) { g->release(); - return new GlyphData(glyph, GlyphMetrics(), GlyphData::FORMAT_RGBA); + return new GlyphData(glyph, GlyphMetrics(), PIXELFORMAT_RGBA8); } image::ImageData *imagedata = imagepair->second.get(); @@ -343,6 +343,11 @@ float BMFontRasterizer::getKerning(uint32 leftglyph, uint32 rightglyph) const return 0.0f; } +Rasterizer::DataType BMFontRasterizer::getDataType() const +{ + return DATA_IMAGE; +} + bool BMFontRasterizer::accepts(love::filesystem::FileData *fontdef) { const char *data = (const char *) fontdef->getData(); diff --git a/src/modules/font/BMFontRasterizer.h b/src/modules/font/BMFontRasterizer.h index f5005ff5f..845841dc3 100644 --- a/src/modules/font/BMFontRasterizer.h +++ b/src/modules/font/BMFontRasterizer.h @@ -51,6 +51,7 @@ public: int getGlyphCount() const override; bool hasGlyph(uint32 glyph) const override; float getKerning(uint32 leftglyph, uint32 rightglyph) const override; + DataType getDataType() const override; static bool accepts(love::filesystem::FileData *fontdef); diff --git a/src/modules/font/GlyphData.cpp b/src/modules/font/GlyphData.cpp index 191e3de68..e2b366e0b 100644 --- a/src/modules/font/GlyphData.cpp +++ b/src/modules/font/GlyphData.cpp @@ -35,12 +35,15 @@ namespace font love::Type GlyphData::type("GlyphData", &Data::type); -GlyphData::GlyphData(uint32 glyph, GlyphMetrics glyphMetrics, GlyphData::Format f) +GlyphData::GlyphData(uint32 glyph, GlyphMetrics glyphMetrics, PixelFormat f) : glyph(glyph) , metrics(glyphMetrics) , data(nullptr) , format(f) { + if (f != PIXELFORMAT_LA8 && f != PIXELFORMAT_RGBA8) + throw love::Exception("Invalid GlyphData pixel format."); + if (metrics.width > 0 && metrics.height > 0) data = new uint8[metrics.width * metrics.height * getPixelSize()]; } @@ -57,14 +60,7 @@ void *GlyphData::getData() const size_t GlyphData::getPixelSize() const { - switch (format) - { - case FORMAT_LUMINANCE_ALPHA: - return 2; - case FORMAT_RGBA: - default: - return 4; - } + return getPixelFormatSize(format); } void *GlyphData::getData(int x, int y) const @@ -150,28 +146,10 @@ int GlyphData::getMaxY() const return getBearingY(); } -GlyphData::Format GlyphData::getFormat() const +PixelFormat GlyphData::getFormat() const { return format; } -bool GlyphData::getConstant(const char *in, GlyphData::Format &out) -{ - return formats.find(in, out); -} - -bool GlyphData::getConstant(GlyphData::Format in, const char *&out) -{ - return formats.find(in, out); -} - -StringMap::Entry GlyphData::formatEntries[] = -{ - {"luminancealpha", FORMAT_LUMINANCE_ALPHA}, - {"rgba", FORMAT_RGBA}, -}; - -StringMap GlyphData::formats(GlyphData::formatEntries, sizeof(GlyphData::formatEntries)); - } // font } // love diff --git a/src/modules/font/GlyphData.h b/src/modules/font/GlyphData.h index d5fcfc11d..00deea357 100644 --- a/src/modules/font/GlyphData.h +++ b/src/modules/font/GlyphData.h @@ -27,6 +27,7 @@ #include "common/Exception.h" #include "common/StringMap.h" #include "common/int.h" +#include "common/pixelformat.h" // stdlib #include @@ -57,14 +58,7 @@ public: static love::Type type; - enum Format - { - FORMAT_LUMINANCE_ALPHA, - FORMAT_RGBA, - FORMAT_MAX_ENUM - }; - - GlyphData(uint32 glyph, GlyphMetrics glyphMetrics, Format f); + GlyphData(uint32 glyph, GlyphMetrics glyphMetrics, PixelFormat f); virtual ~GlyphData(); // Implements Data. @@ -139,10 +133,7 @@ public: /** * Gets the format of the glyph data. **/ - Format getFormat() const; - - static bool getConstant(const char *in, Format &out); - static bool getConstant(Format in, const char *&out); + PixelFormat getFormat() const; private: @@ -156,10 +147,7 @@ private: uint8 *data; // The format the data's in. - Format format; - - static StringMap::Entry formatEntries[]; - static StringMap formats; + PixelFormat format; }; // GlyphData diff --git a/src/modules/font/ImageRasterizer.cpp b/src/modules/font/ImageRasterizer.cpp index a1da11da4..ad79131ac 100644 --- a/src/modules/font/ImageRasterizer.cpp +++ b/src/modules/font/ImageRasterizer.cpp @@ -69,7 +69,7 @@ GlyphData *ImageRasterizer::getGlyphData(uint32 glyph) const gm.height = metrics.height; - GlyphData *g = new GlyphData(glyph, gm, GlyphData::FORMAT_RGBA); + GlyphData *g = new GlyphData(glyph, gm, PIXELFORMAT_RGBA8); if (gm.width == 0) return g; @@ -149,5 +149,10 @@ bool ImageRasterizer::hasGlyph(uint32 glyph) const return imageGlyphs.find(glyph) != imageGlyphs.end(); } +Rasterizer::DataType ImageRasterizer::getDataType() const +{ + return DATA_IMAGE; +} + } // font } // love diff --git a/src/modules/font/ImageRasterizer.h b/src/modules/font/ImageRasterizer.h index 331b40758..199e8504e 100644 --- a/src/modules/font/ImageRasterizer.h +++ b/src/modules/font/ImageRasterizer.h @@ -43,10 +43,12 @@ public: virtual ~ImageRasterizer(); // Implement Rasterizer - virtual int getLineHeight() const; - virtual GlyphData *getGlyphData(uint32 glyph) const; - virtual int getGlyphCount() const; - virtual bool hasGlyph(uint32 glyph) const; + int getLineHeight() const override; + GlyphData *getGlyphData(uint32 glyph) const override; + int getGlyphCount() const override; + bool hasGlyph(uint32 glyph) const override; + DataType getDataType() const override; + private: diff --git a/src/modules/font/Rasterizer.h b/src/modules/font/Rasterizer.h index 0536a9119..40b72d5e5 100644 --- a/src/modules/font/Rasterizer.h +++ b/src/modules/font/Rasterizer.h @@ -49,6 +49,12 @@ class Rasterizer : public Object { public: + enum DataType + { + DATA_TRUETYPE, + DATA_IMAGE, + }; + static love::Type type; virtual ~Rasterizer(); @@ -112,6 +118,8 @@ public: **/ virtual float getKerning(uint32 leftglyph, uint32 rightglyph) const; + virtual DataType getDataType() const = 0; + protected: FontMetrics metrics; diff --git a/src/modules/font/freetype/TrueTypeRasterizer.cpp b/src/modules/font/freetype/TrueTypeRasterizer.cpp index 55caf0e2a..915a12648 100644 --- a/src/modules/font/freetype/TrueTypeRasterizer.cpp +++ b/src/modules/font/freetype/TrueTypeRasterizer.cpp @@ -108,7 +108,7 @@ GlyphData *TrueTypeRasterizer::getGlyphData(uint32 glyph) const glyphMetrics.width = bitmap.width; glyphMetrics.advance = (int) (ftglyph->advance.x >> 16); - GlyphData *glyphData = new GlyphData(glyph, glyphMetrics, GlyphData::FORMAT_LUMINANCE_ALPHA); + GlyphData *glyphData = new GlyphData(glyph, glyphMetrics, PIXELFORMAT_LA8); const uint8 *pixels = bitmap.buffer; uint8 *dest = (uint8 *) glyphData->getData(); @@ -176,6 +176,11 @@ float TrueTypeRasterizer::getKerning(uint32 leftglyph, uint32 rightglyph) const return float(kerning.x >> 6); } +Rasterizer::DataType TrueTypeRasterizer::getDataType() const +{ + return DATA_TRUETYPE; +} + bool TrueTypeRasterizer::accepts(FT_Library library, love::Data *data) { const FT_Byte *fbase = (const FT_Byte *) data->getData(); diff --git a/src/modules/font/freetype/TrueTypeRasterizer.h b/src/modules/font/freetype/TrueTypeRasterizer.h index c8247fa86..b53824267 100644 --- a/src/modules/font/freetype/TrueTypeRasterizer.h +++ b/src/modules/font/freetype/TrueTypeRasterizer.h @@ -48,11 +48,12 @@ public: virtual ~TrueTypeRasterizer(); // Implement Rasterizer - virtual int getLineHeight() const; - virtual GlyphData *getGlyphData(uint32 glyph) const; - virtual int getGlyphCount() const; - virtual bool hasGlyph(uint32 glyph) const; - virtual float getKerning(uint32 leftglyph, uint32 rightglyph) const; + int getLineHeight() const override; + GlyphData *getGlyphData(uint32 glyph) const override; + int getGlyphCount() const override; + bool hasGlyph(uint32 glyph) const override; + float getKerning(uint32 leftglyph, uint32 rightglyph) const override; + DataType getDataType() const override; static bool accepts(FT_Library library, love::Data *data); diff --git a/src/modules/font/wrap_GlyphData.cpp b/src/modules/font/wrap_GlyphData.cpp index 03f5c2a56..adab429dc 100644 --- a/src/modules/font/wrap_GlyphData.cpp +++ b/src/modules/font/wrap_GlyphData.cpp @@ -108,7 +108,7 @@ int w_GlyphData_getFormat(lua_State *L) GlyphData *t = luax_checkglyphdata(L, 1); const char *str; - if (!GlyphData::getConstant(t->getFormat(), str)) + if (!getConstant(t->getFormat(), str)) return luaL_error(L, "unknown GlyphData format."); lua_pushstring(L, str); diff --git a/src/modules/graphics/opengl/Font.cpp b/src/modules/graphics/opengl/Font.cpp index 4ab23f50c..be864cac3 100644 --- a/src/modules/graphics/opengl/Font.cpp +++ b/src/modules/graphics/opengl/Font.cpp @@ -78,7 +78,7 @@ Font::Font(love::font::Rasterizer *r, const Texture::Filter &filter) } love::font::GlyphData *gd = r->getGlyphData(32); // Space character. - fontType = (gd->getFormat() == font::GlyphData::FORMAT_LUMINANCE_ALPHA) ? FONT_TRUETYPE : FONT_IMAGE; + pixelFormat = gd->getFormat(); gd->release(); if (!r->hasGlyph(9)) // No tab character in the Rasterizer. @@ -114,31 +114,6 @@ Font::TextureSize Font::getNextTextureSize() const return size; } -GLenum Font::getTextureFormat(FontType fontType, GLenum *internalformat) const -{ - GLenum format = fontType == FONT_TRUETYPE ? GL_LUMINANCE_ALPHA : GL_RGBA; - GLenum iformat = fontType == FONT_TRUETYPE ? GL_LUMINANCE8_ALPHA8 : GL_RGBA8; - - if (format == GL_RGBA && isGammaCorrect()) - { - // In ES2, the internalformat and format params of TexImage must match. - // ES3 doesn't allow "GL_SRGB_ALPHA" as the internal format. But it also - // requires GL_LUMINANCE_ALPHA rather than GL_LUMINANCE8_ALPHA8 as the - // internal format, for LA. - if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0) - format = iformat = GL_SRGB_ALPHA; - else - iformat = GL_SRGB8_ALPHA8; - } - else if (GLAD_ES_VERSION_2_0) - iformat = format; - - if (internalformat != nullptr) - *internalformat = iformat; - - return format; -} - void Font::createTexture() { auto gfx = Module::getInstance(Module::M_GRAPHICS); @@ -146,7 +121,7 @@ void Font::createTexture() OpenGL::TempDebugGroup debuggroup("Font create texture"); - size_t bpp = fontType == FONT_TRUETYPE ? 2 : 4; + size_t bpp = getPixelFormatSize(pixelFormat); size_t prevmemsize = textureMemorySize; if (prevmemsize > 0) @@ -180,8 +155,8 @@ void Font::createTexture() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - GLenum internalformat = GL_RGBA; - GLenum format = getTextureFormat(fontType, &internalformat); + bool sRGB = isGammaCorrect(); + OpenGL::TextureFormat fmt = gl.convertPixelFormat(pixelFormat, false, sRGB); // Initialize the texture with transparent black. std::vector emptydata(size.width * size.height * bpp, 0); @@ -189,8 +164,8 @@ void Font::createTexture() // Clear errors before initializing. while (glGetError() != GL_NO_ERROR); - glTexImage2D(GL_TEXTURE_2D, 0, internalformat, size.width, size.height, 0, - format, GL_UNSIGNED_BYTE, &emptydata[0]); + glTexImage2D(GL_TEXTURE_2D, 0, fmt.internalformat, size.width, size.height, + 0, fmt.externalformat, fmt.type, &emptydata[0]); if (glGetError() != GL_NO_ERROR) { @@ -233,7 +208,7 @@ love::font::GlyphData *Font::getRasterizerGlyphData(uint32 glyph) if (glyph == 9 && useSpacesAsTab) { love::font::GlyphData *spacegd = rasterizers[0]->getGlyphData(32); - love::font::GlyphData::Format fmt = spacegd->getFormat(); + PixelFormat fmt = spacegd->getFormat(); love::font::GlyphMetrics gm = {}; gm.advance = spacegd->getAdvance() * SPACES_PER_TAB; @@ -289,12 +264,14 @@ const Font::Glyph &Font::addGlyph(uint32 glyph) // don't waste space for empty glyphs. also fixes a divide by zero bug with ATI drivers if (w > 0 && h > 0) { - GLenum format = getTextureFormat(fontType); + bool isSRGB = isGammaCorrect(); + OpenGL::TextureFormat fmt = gl.convertPixelFormat(pixelFormat, false, isSRGB); + g.texture = textures.back(); gl.bindTextureToUnit(g.texture, 0, false); glTexSubImage2D(GL_TEXTURE_2D, 0, textureX, textureY, w, h, - format, GL_UNSIGNED_BYTE, gd->getData()); + fmt.externalformat, fmt.type, gd->getData()); double tX = (double) textureX, tY = (double) textureY; double tWidth = (double) textureWidth, tHeight = (double) textureHeight; @@ -979,7 +956,10 @@ int Font::getDescent() const float Font::getBaseline() const { // 1.25 is magic line height for true type fonts - return (fontType == FONT_TRUETYPE) ? floorf(getHeight() / 1.25f + 0.5f) : 0.0f; + if (rasterizers[0]->getDataType() == font::Rasterizer::DATA_TRUETYPE) + return floorf(getHeight() / 1.25f + 0.5f); + else + return 0.0f; } bool Font::hasGlyph(uint32 glyph) const @@ -1023,7 +1003,7 @@ void Font::setFallbacks(const std::vector &fallbacks) { for (const Font *f : fallbacks) { - if (f->fontType != this->fontType) + if (f->rasterizers[0]->getDataType() != this->rasterizers[0]->getDataType()) throw love::Exception("Font fallbacks must be of the same font type."); } diff --git a/src/modules/graphics/opengl/Font.h b/src/modules/graphics/opengl/Font.h index bdfb8a8bb..3b9fbd3f8 100644 --- a/src/modules/graphics/opengl/Font.h +++ b/src/modules/graphics/opengl/Font.h @@ -188,13 +188,6 @@ public: private: - enum FontType - { - FONT_TRUETYPE, - FONT_IMAGE, - FONT_UNKNOWN - }; - struct Glyph { GLuint texture; @@ -209,7 +202,6 @@ private: }; TextureSize getNextTextureSize() const; - GLenum getTextureFormat(FontType fontType, GLenum *internalformat = nullptr) const; void createTexture(); love::font::GlyphData *getRasterizerGlyphData(uint32 glyph); const Glyph &addGlyph(uint32 glyph); @@ -234,7 +226,8 @@ private: // map of left/right glyph pairs to horizontal kerning. std::unordered_map kerning; - FontType fontType; + PixelFormat pixelFormat; + Texture::Filter filter; int textureX, textureY; diff --git a/src/modules/graphics/opengl/OpenGL.cpp b/src/modules/graphics/opengl/OpenGL.cpp index 51b026320..df02cc663 100644 --- a/src/modules/graphics/opengl/OpenGL.cpp +++ b/src/modules/graphics/opengl/OpenGL.cpp @@ -812,6 +812,12 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r f.type = GL_FLOAT; break; + case PIXELFORMAT_LA8: + f.internalformat = GL_LUMINANCE8_ALPHA8; + f.externalformat = GL_LUMINANCE_ALPHA; + f.type = GL_UNSIGNED_BYTE; + break; + case PIXELFORMAT_RGBA4: f.internalformat = GL_RGBA4; f.externalformat = GL_RGBA; @@ -965,8 +971,11 @@ OpenGL::TextureFormat OpenGL::convertPixelFormat(PixelFormat pixelformat, bool r if (!isPixelFormatCompressed(pixelformat)) { - if (GLAD_ES_VERSION_2_0 && !GLAD_ES_VERSION_3_0 && !renderbuffer) + if (GLAD_ES_VERSION_2_0 && !(GLAD_ES_VERSION_3_0 && pixelformat != PIXELFORMAT_LA8) + && !renderbuffer) + { f.internalformat = f.externalformat; + } if (pixelformat != PIXELFORMAT_sRGBA8) isSRGB = false; @@ -1048,6 +1057,9 @@ bool OpenGL::isPixelFormatSupported(PixelFormat pixelformat, bool rendertarget, else return false; + case PIXELFORMAT_LA8: + return !rendertarget; + case PIXELFORMAT_RGBA4: case PIXELFORMAT_RGB5A1: return true;