mirror of
https://github.com/love2d/love.git
synced 2026-08-17 19:23:38 +02:00
Font objects now have mipmap filter and mipmap sharpness support
This commit is contained in:
@@ -21,15 +21,15 @@
|
|||||||
#include "Font.h"
|
#include "Font.h"
|
||||||
#include "font/GlyphData.h"
|
#include "font/GlyphData.h"
|
||||||
#include "Quad.h"
|
#include "Quad.h"
|
||||||
|
#include "Image.h"
|
||||||
|
|
||||||
#include "libraries/utf8/utf8.h"
|
#include "libraries/utf8/utf8.h"
|
||||||
|
|
||||||
#include "common/math.h"
|
#include "common/math.h"
|
||||||
#include "common/Matrix.h"
|
#include "common/Matrix.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <algorithm> // for max
|
#include <algorithm> // for max
|
||||||
|
|
||||||
namespace love
|
namespace love
|
||||||
@@ -48,6 +48,7 @@ Font::Font(love::font::Rasterizer *r, const Image::Filter &filter)
|
|||||||
, lineHeight(1)
|
, lineHeight(1)
|
||||||
, mSpacing(1)
|
, mSpacing(1)
|
||||||
, filter(filter)
|
, filter(filter)
|
||||||
|
, mipmapsharpness(0.0f)
|
||||||
{
|
{
|
||||||
love::font::GlyphData *gd = r->getGlyphData(32);
|
love::font::GlyphData *gd = r->getGlyphData(32);
|
||||||
type = (gd->getFormat() == love::font::GlyphData::FORMAT_LUMINANCE_ALPHA ? FONT_TRUETYPE : FONT_IMAGE);
|
type = (gd->getFormat() == love::font::GlyphData::FORMAT_LUMINANCE_ALPHA ? FONT_TRUETYPE : FONT_IMAGE);
|
||||||
@@ -70,7 +71,7 @@ Font::Font(love::font::Rasterizer *r, const Image::Filter &filter)
|
|||||||
texture_width = TEXTURE_WIDTHS[texture_size_index];
|
texture_width = TEXTURE_WIDTHS[texture_size_index];
|
||||||
texture_height = TEXTURE_HEIGHTS[texture_size_index];
|
texture_height = TEXTURE_HEIGHTS[texture_size_index];
|
||||||
|
|
||||||
createTexture();
|
loadVolatile();
|
||||||
|
|
||||||
r->retain();
|
r->retain();
|
||||||
}
|
}
|
||||||
@@ -111,7 +112,8 @@ void Font::createTexture()
|
|||||||
|
|
||||||
bindTexture(t);
|
bindTexture(t);
|
||||||
|
|
||||||
setTextureFilter(filter);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
@@ -153,6 +155,9 @@ void Font::createTexture()
|
|||||||
format,
|
format,
|
||||||
GL_UNSIGNED_BYTE,
|
GL_UNSIGNED_BYTE,
|
||||||
&emptyData[0]);
|
&emptyData[0]);
|
||||||
|
|
||||||
|
setFilter(filter);
|
||||||
|
setMipmapSharpness(mipmapsharpness);
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::Glyph *Font::addGlyph(const int glyph)
|
Font::Glyph *Font::addGlyph(const int glyph)
|
||||||
@@ -484,30 +489,85 @@ float Font::getSpacing() const
|
|||||||
return mSpacing;
|
return mSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Font::checkMipmapsCreated() const
|
||||||
|
{
|
||||||
|
if (filter.mipmap != Image::FILTER_NEAREST && filter.mipmap != Image::FILTER_LINEAR)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!Image::hasMipmapSupport())
|
||||||
|
throw love::Exception("Mipmap filtering is not supported on this system!");
|
||||||
|
|
||||||
|
GLboolean mipmapscreated;
|
||||||
|
glGetTexParameteriv(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, (GLint *)&mipmapscreated);
|
||||||
|
|
||||||
|
// generate mipmaps for this image if we haven't already
|
||||||
|
if (!mipmapscreated)
|
||||||
|
{
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
|
||||||
|
|
||||||
|
if (GLEE_VERSION_3_0 || GLEE_ARB_framebuffer_object)
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
else if (GLEE_EXT_framebuffer_object)
|
||||||
|
glGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// modify single texel to trigger mipmap chain generation
|
||||||
|
std::vector<GLubyte> emptydata(type == FONT_TRUETYPE ? 2 : 4);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D,
|
||||||
|
0,
|
||||||
|
0, 0,
|
||||||
|
1, 1,
|
||||||
|
type == FONT_TRUETYPE ? GL_LUMINANCE_ALPHA : GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
&emptydata[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Font::setFilter(const Image::Filter &f)
|
void Font::setFilter(const Image::Filter &f)
|
||||||
{
|
{
|
||||||
|
filter = f;
|
||||||
|
|
||||||
std::vector<GLuint>::const_iterator it;
|
std::vector<GLuint>::const_iterator it;
|
||||||
for (it = textures.begin(); it != textures.end(); ++it)
|
for (it = textures.begin(); it != textures.end(); ++it)
|
||||||
{
|
{
|
||||||
bindTexture(*it);
|
bindTexture(*it);
|
||||||
|
checkMipmapsCreated();
|
||||||
setTextureFilter(f);
|
setTextureFilter(f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image::Filter Font::getFilter()
|
const Image::Filter &Font::getFilter()
|
||||||
{
|
{
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Font::setMipmapSharpness(float sharpness)
|
||||||
|
{
|
||||||
|
if (!Image::hasMipmapSharpnessSupport())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// LOD bias has the range (-maxbias, maxbias)
|
||||||
|
mipmapsharpness = std::min(std::max(sharpness, -maxmipmapsharpness + 0.01f), maxmipmapsharpness - 0.01f);
|
||||||
|
|
||||||
std::vector<GLuint>::const_iterator it;
|
std::vector<GLuint>::const_iterator it;
|
||||||
for (it = textures.begin(); it != textures.end(); ++it)
|
for (it = textures.begin(); it != textures.end(); ++it)
|
||||||
{
|
{
|
||||||
bindTexture(*it);
|
bindTexture(*it);
|
||||||
return getTextureFilter();
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, -mipmapsharpness); // negative bias is sharper
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Image::getDefaultFilter();
|
float Font::getMipmapSharpness() const
|
||||||
|
{
|
||||||
|
return mipmapsharpness;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Font::loadVolatile()
|
bool Font::loadVolatile()
|
||||||
{
|
{
|
||||||
|
if (Image::hasMipmapSharpnessSupport())
|
||||||
|
glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS, &maxmipmapsharpness);
|
||||||
|
|
||||||
createTexture();
|
createTexture();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,10 @@ public:
|
|||||||
float getSpacing() const;
|
float getSpacing() const;
|
||||||
|
|
||||||
void setFilter(const Image::Filter &f);
|
void setFilter(const Image::Filter &f);
|
||||||
Image::Filter getFilter();
|
const Image::Filter &getFilter();
|
||||||
|
|
||||||
|
void setMipmapSharpness(float sharpness);
|
||||||
|
float getMipmapSharpness() const;
|
||||||
|
|
||||||
// Implements Volatile.
|
// Implements Volatile.
|
||||||
bool loadVolatile();
|
bool loadVolatile();
|
||||||
@@ -196,6 +199,14 @@ private:
|
|||||||
int texture_x, texture_y;
|
int texture_x, texture_y;
|
||||||
int rowHeight;
|
int rowHeight;
|
||||||
|
|
||||||
|
// Mipmap texture LOD bias value
|
||||||
|
float mipmapsharpness;
|
||||||
|
|
||||||
|
// Implementation-dependent maximum/minimum mipmap sharpness values
|
||||||
|
float maxmipmapsharpness;
|
||||||
|
|
||||||
|
void checkMipmapsCreated() const;
|
||||||
|
|
||||||
bool initializeTexture(GLint format);
|
bool initializeTexture(GLint format);
|
||||||
void createTexture();
|
void createTexture();
|
||||||
Glyph *addGlyph(const int glyph);
|
Glyph *addGlyph(const int glyph);
|
||||||
|
|||||||
@@ -104,7 +104,23 @@ int w_Font_setFilter(lua_State *L)
|
|||||||
if (!Image::getConstant(magstr, f.mag))
|
if (!Image::getConstant(magstr, f.mag))
|
||||||
return luaL_error(L, "Invalid filter mode: %s", magstr);
|
return luaL_error(L, "Invalid filter mode: %s", magstr);
|
||||||
|
|
||||||
|
if (lua_isnoneornil(L, 4))
|
||||||
|
f.mipmap = Image::FILTER_NONE; // mipmapping is disabled unless third argument is given
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const char *mipmapstr = luaL_checkstring(L, 4);
|
||||||
|
if (!Image::getConstant(mipmapstr, f.mipmap))
|
||||||
|
return luaL_error(L, "Invalid filter mode: %s", mipmapstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
t->setFilter(f);
|
t->setFilter(f);
|
||||||
|
}
|
||||||
|
catch(love::Exception &e)
|
||||||
|
{
|
||||||
|
return luaL_error(L, "%s", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -119,7 +135,31 @@ int w_Font_getFilter(lua_State *L)
|
|||||||
Image::getConstant(f.mag, magstr);
|
Image::getConstant(f.mag, magstr);
|
||||||
lua_pushstring(L, minstr);
|
lua_pushstring(L, minstr);
|
||||||
lua_pushstring(L, magstr);
|
lua_pushstring(L, magstr);
|
||||||
return 2;
|
|
||||||
|
const char *mipmapstr;
|
||||||
|
if (Image::getConstant(f.mipmap, mipmapstr))
|
||||||
|
lua_pushstring(L, mipmapstr);
|
||||||
|
else
|
||||||
|
lua_pushnil(L); // only return a mipmap filter if mipmapping is enabled
|
||||||
|
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w_Font_setMipmapSharpness(lua_State *L)
|
||||||
|
{
|
||||||
|
Font *t = luax_checkfont(L, 1);
|
||||||
|
|
||||||
|
float sharpness = (float) luaL_checknumber(L, 2);
|
||||||
|
t->setMipmapSharpness(sharpness);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int w_Font_getMipmapSharpness(lua_State *L)
|
||||||
|
{
|
||||||
|
Font *t = luax_checkfont(L, 1);
|
||||||
|
lua_pushnumber(L, t->getMipmapSharpness());
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const luaL_Reg functions[] =
|
static const luaL_Reg functions[] =
|
||||||
@@ -131,6 +171,8 @@ static const luaL_Reg functions[] =
|
|||||||
{ "getLineHeight", w_Font_getLineHeight },
|
{ "getLineHeight", w_Font_getLineHeight },
|
||||||
{ "setFilter", w_Font_setFilter },
|
{ "setFilter", w_Font_setFilter },
|
||||||
{ "getFilter", w_Font_getFilter },
|
{ "getFilter", w_Font_getFilter },
|
||||||
|
{ "setMipmapSharpness", w_Font_setMipmapSharpness },
|
||||||
|
{ "getMipmapSharpness", w_Font_getMipmapSharpness },
|
||||||
{ 0, 0 }
|
{ 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ int w_Font_setLineHeight(lua_State *L);
|
|||||||
int w_Font_getLineHeight(lua_State *L);
|
int w_Font_getLineHeight(lua_State *L);
|
||||||
int w_Font_setFilter(lua_State *L);
|
int w_Font_setFilter(lua_State *L);
|
||||||
int w_Font_getFilter(lua_State *L);
|
int w_Font_getFilter(lua_State *L);
|
||||||
|
int w_Font_setMipmapSharpness(lua_State *L);
|
||||||
|
int w_Font_getMipmapSharpness(lua_State *L);
|
||||||
extern "C" int luaopen_font(lua_State *L);
|
extern "C" int luaopen_font(lua_State *L);
|
||||||
|
|
||||||
} // opengl
|
} // opengl
|
||||||
|
|||||||
Reference in New Issue
Block a user