Exposed the internal Rasterizer and GlyphData object methods to Lua. Also added Font:hasGlyph.

This commit is contained in:
Alex Szpakowski
2013-06-16 07:36:18 -03:00
parent dd9cca1a55
commit d48d1fd441
21 changed files with 449 additions and 24 deletions
+1
View File
@@ -42,6 +42,7 @@ public:
virtual Rasterizer *newRasterizer(Data *data, int size) = 0;
virtual Rasterizer *newRasterizer(love::image::ImageData *data, const std::string &glyphs) = 0;
virtual Rasterizer *newRasterizer(love::image::ImageData *data, unsigned int *glyphs, int length) = 0;
virtual GlyphData *newGlyphData(Rasterizer *r, const std::string &glyph) = 0;
virtual GlyphData *newGlyphData(Rasterizer *r, unsigned int glyph) = 0;
// Implement Module
+46 -1
View File
@@ -18,8 +18,13 @@
* 3. This notice may not be removed or altered from any source distribution.
**/
// LOVE
#include "GlyphData.h"
// UTF-8
#include "libraries/utf8/utf8.h"
// stdlib
#include <iostream>
namespace love
@@ -33,7 +38,7 @@ GlyphData::GlyphData(unsigned int glyph, GlyphMetrics glyphMetrics, GlyphData::F
, data(0)
, format(f)
{
if (metrics.width && metrics.height)
if (metrics.width > 0 && metrics.height > 0)
{
switch (f)
{
@@ -88,6 +93,28 @@ unsigned int GlyphData::getGlyph() const
return glyph;
}
std::string GlyphData::getGlyphString() const
{
char u[5] = {0, 0, 0, 0, 0};
ptrdiff_t length = 0;
try
{
char *end = utf8::append(glyph, u);
length = end - u;
}
catch (utf8::exception &e)
{
throw love::Exception("Decoding error: %s", e.what());
}
// Just in case...
if (length < 0)
return "";
return std::string(u, length);
}
int GlyphData::getAdvance() const
{
return metrics.advance;
@@ -128,5 +155,23 @@ GlyphData::Format 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<GlyphData::Format, GlyphData::FORMAT_MAX_ENUM>::Entry GlyphData::formatEntries[] =
{
{"luminance alpha", GlyphData::FORMAT_LUMINANCE_ALPHA},
{"rgba", GlyphData::FORMAT_RGBA},
};
StringMap<GlyphData::Format, GlyphData::FORMAT_MAX_ENUM> GlyphData::formats(GlyphData::formatEntries, sizeof(GlyphData::formatEntries));
} // font
} // love
+24 -6
View File
@@ -24,6 +24,11 @@
// LOVE
#include "common/config.h"
#include "common/Data.h"
#include "common/Exception.h"
#include "common/StringMap.h"
// stdlib
#include <string>
namespace love
{
@@ -48,12 +53,13 @@ struct GlyphMetrics
**/
class GlyphData : public Data
{
public:
enum Format
{
FORMAT_LUMINANCE_ALPHA,
FORMAT_RGBA
FORMAT_RGBA,
FORMAT_MAX_ENUM
};
GlyphData(unsigned int glyph, GlyphMetrics glyphMetrics, Format f);
@@ -78,6 +84,11 @@ public:
**/
unsigned int getGlyph() const;
/**
* Gets the glyph as a UTF-8 string (instead of a UTF-8 code point.)
**/
std::string getGlyphString() const;
/**
* Gets the advance (the space the glyph takes up) of the glyph.
**/
@@ -118,19 +129,26 @@ public:
**/
Format getFormat() const;
static bool getConstant(const char *in, Format &out);
static bool getConstant(Format in, const char *&out);
private:
// The glyph itself
// The glyph codepoint itself.
unsigned int glyph;
// Glyph metrics
// Glyph metrics.
GlyphMetrics metrics;
// Glyph texture data
// Glyph texture data.
unsigned char *data;
// The format the data's in
// The format the data's in.
Format format;
static StringMap<Format, FORMAT_MAX_ENUM>::Entry formatEntries[];
static StringMap<Format, FORMAT_MAX_ENUM> formats;
}; // GlyphData
} // font
+5
View File
@@ -151,5 +151,10 @@ int ImageRasterizer::getGlyphCount() const
return numglyphs;
}
bool ImageRasterizer::hasGlyph(unsigned int glyph) const
{
return imageGlyphs.find(glyph) != imageGlyphs.end();
}
} // font
} // love
+1
View File
@@ -46,6 +46,7 @@ public:
virtual int getLineHeight() const;
virtual GlyphData *getGlyphData(unsigned int glyph) const;
virtual int getGlyphCount() const;
virtual bool hasGlyph(unsigned int glyph) const;
private:
// Load all the glyph positions into memory
+38
View File
@@ -21,6 +21,9 @@
// LOVE
#include "Rasterizer.h"
// UTF-8
#include "libraries/utf8/utf8.h"
namespace love
{
namespace font
@@ -50,5 +53,40 @@ int Rasterizer::getDescent() const
return metrics.descent;
}
GlyphData *Rasterizer::getGlyphData(const std::string &text) const
{
unsigned int codepoint = 0;
try
{
codepoint = utf8::peek_next(text.begin(), text.end());
}
catch (utf8::exception &e)
{
throw love::Exception("Decoding error: %s", e.what());
}
return getGlyphData(codepoint);
}
bool Rasterizer::hasGlyph(const std::string &text) const
{
if (text.size() == 0)
return false;
unsigned int codepoint = 0;
try
{
codepoint = utf8::peek_next(text.begin(), text.end());
}
catch (utf8::exception &e)
{
throw love::Exception("Decoding error: %s", e.what());
}
return hasGlyph(codepoint);
}
} // font
} // love
+22 -4
View File
@@ -46,9 +46,6 @@ struct FontMetrics
**/
class Rasterizer : public Object
{
protected:
FontMetrics metrics;
public:
virtual ~Rasterizer();
@@ -80,15 +77,36 @@ public:
/**
* Gets a specific glyph.
* @param glyph The (UNICODE) glyph to get data for
* @param glyph The (UNICODE) glyph codepoint to get data for.
**/
virtual GlyphData *getGlyphData(unsigned int glyph) const = 0;
/**
* Gets a specific glyph.
* @param text The (UNICODE) glyph character to get the data for.
**/
virtual GlyphData *getGlyphData(const std::string &text) const;
/**
* Gets the number of glyphs the rasterizer has data for.
**/
virtual int getGlyphCount() const = 0;
/**
* Gets whether this Rasterizer has a specific glyph.
* @param glyph The (UNICODE) glyph codepoint.
**/
virtual bool hasGlyph(unsigned int glyph) const = 0;
/**
* Gets whether this Rasterizer has a specific glyph.
* @param text The (UNICODE) glyph character.
**/
virtual bool hasGlyph(const std::string &text) const;
protected:
FontMetrics metrics;
}; // Rasterizer
+19 -3
View File
@@ -66,12 +66,12 @@ Rasterizer *Font::newRasterizer(love::image::ImageData *data, const std::string
catch (utf8::exception &e)
{
delete [] glyphs;
throw love::Exception("%s", e.what());
throw love::Exception("Decoding error: %s", e.what());
}
Rasterizer *r = newRasterizer(data, glyphs, numglyphs);
delete [] glyphs;
return r;
}
@@ -80,6 +80,22 @@ Rasterizer *Font::newRasterizer(love::image::ImageData *data, unsigned int *glyp
return new ImageRasterizer(data, glyphs, numglyphs);
}
GlyphData *Font::newGlyphData(Rasterizer *r, const std::string &text)
{
unsigned int codepoint = 0;
try
{
codepoint = utf8::peek_next(text.begin(), text.end());
}
catch (utf8::exception &e)
{
throw love::Exception("Decoding error: %s", e.what());
}
return r->getGlyphData(codepoint);
}
GlyphData *Font::newGlyphData(Rasterizer *r, unsigned int glyph)
{
return r->getGlyphData(glyph);
+1
View File
@@ -57,6 +57,7 @@ public:
Rasterizer *newRasterizer(Data *data, int size);
Rasterizer *newRasterizer(love::image::ImageData *data, const std::string &text);
Rasterizer *newRasterizer(love::image::ImageData *data, unsigned int *glyphs, int numglyphs);
GlyphData *newGlyphData(Rasterizer *r, const std::string &glyph);
GlyphData *newGlyphData(Rasterizer *r, unsigned int glyph);
// Implement Module
@@ -91,8 +91,8 @@ GlyphData *TrueTypeRasterizer::getGlyphData(unsigned int glyph) const
int size = bitmap.rows * bitmap.width;
unsigned char *dst = (unsigned char *) glyphData->getData();
// Note that bitmap.buffer contains only luminosity. We copy that single value to
// our luminosity-alpha format.
// Note that bitmap.buffer contains only luminosity. We copy that single
// value to our luminosity-alpha format.
for (int i = 0; i < size; i++)
{
dst[2*i] = 255;
@@ -111,6 +111,11 @@ int TrueTypeRasterizer::getGlyphCount() const
return face->num_glyphs;
}
bool TrueTypeRasterizer::hasGlyph(unsigned int glyph) const
{
return FT_Get_Char_Index(face, glyph) != 0;
}
} // freetype
} // font
} // love
@@ -52,6 +52,7 @@ public:
virtual int getLineHeight() const;
virtual GlyphData *getGlyphData(unsigned int glyph) const;
virtual int getGlyphCount() const;
virtual bool hasGlyph(unsigned int glyph) const;
private:
+24 -2
View File
@@ -38,6 +38,10 @@ static Font *instance = 0;
int w_newRasterizer(lua_State *L)
{
// Convert to FileData, if necessary.
if (lua_isstring(L, 1) || luax_istype(L, 1, FILESYSTEM_FILE_T))
luax_convobj(L, 1, "filesystem", "newFileData");
Rasterizer *t = NULL;
try
{
@@ -67,9 +71,27 @@ int w_newRasterizer(lua_State *L)
int w_newGlyphData(lua_State *L)
{
Rasterizer *r = luax_checkrasterizer(L, 1);
unsigned int g = (unsigned int)luaL_checknumber(L, 2);
GlyphData *t = 0;
// newGlyphData accepts a unicode character or a codepoint number.
if (lua_type(L, 2) == LUA_TSTRING)
{
std::string glyph = luax_checkstring(L, 2);
try
{
t = instance->newGlyphData(r, glyph);
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
}
else
{
unsigned int g = (unsigned int) luaL_checknumber(L, 2);
t = instance->newGlyphData(r, g);
}
GlyphData *t = instance->newGlyphData(r, g);
luax_newtype(L, "GlyphData", FONT_GLYPH_DATA_T, t);
return 1;
}
+101
View File
@@ -30,11 +30,112 @@ GlyphData *luax_checkglyphdata(lua_State *L, int idx)
return luax_checktype<GlyphData>(L, idx, "GlyphData", FONT_GLYPH_DATA_T);
}
int w_GlyphData_getWidth(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
lua_pushinteger(L, t->getWidth());
return 1;
}
int w_GlyphData_getHeight(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
lua_pushinteger(L, t->getHeight());
return 1;
}
int w_GlyphData_getDimensions(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
lua_pushinteger(L, t->getWidth());
lua_pushinteger(L, t->getHeight());
return 2;
}
int w_GlyphData_getGlyph(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
unsigned int glyph = t->getGlyph();
lua_pushnumber(L, (lua_Number) glyph);
return 1;
}
int w_GlyphData_getGlyphString(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
try
{
luax_pushstring(L, t->getGlyphString());
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
return 1;
}
int w_GlyphData_getAdvance(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
lua_pushinteger(L, t->getAdvance());
return 1;
}
int w_GlyphData_getBearing(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
lua_pushinteger(L, t->getBearingX());
lua_pushinteger(L, t->getBearingY());
return 2;
}
int w_GlyphData_getBoundingBox(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
int minX = t->getMinX();
int minY = t->getMinY();
int maxX = t->getMaxX();
int maxY = t->getMaxY();
int width = maxX - minX;
int height = maxY - minY;
lua_pushinteger(L, minX);
lua_pushinteger(L, minY);
lua_pushinteger(L, width);
lua_pushinteger(L, height);
return 4;
}
int w_GlyphData_getFormat(lua_State *L)
{
GlyphData *t = luax_checkglyphdata(L, 1);
const char *str;
if (!GlyphData::getConstant(t->getFormat(), str))
return luaL_error(L, "unknown GlyphData format.");
lua_pushstring(L, str);
return 1;
}
static const luaL_Reg functions[] =
{
// Data
{ "getString", w_Data_getString },
{ "getSize", w_Data_getSize },
{ "getWidth", w_GlyphData_getWidth },
{ "getHeight", w_GlyphData_getHeight },
{ "getDimensions", w_GlyphData_getDimensions },
{ "getGlyph", w_GlyphData_getGlyph },
{ "getGlyphString", w_GlyphData_getGlyphString },
{ "getAdvance", w_GlyphData_getAdvance },
{ "getBearing", w_GlyphData_getBearing },
{ "getBoundingBox", w_GlyphData_getBoundingBox },
{ "getFormat", w_GlyphData_getFormat },
{ 0, 0 }
};
+9
View File
@@ -33,6 +33,15 @@ namespace font
{
GlyphData *luax_checkglyphdata(lua_State *L, int idx);
int w_GlyphData_getWidth(lua_State *L);
int w_GlyphData_getHeight(lua_State *L);
int w_GlyphData_getDimensions(lua_State *L);
int w_GlyphData_getGlyph(lua_State *L);
int w_GlyphData_getGlyphString(lua_State *L);
int w_GlyphData_getAdvance(lua_State *L);
int w_GlyphData_getBearing(lua_State *L);
int w_GlyphData_getBoundingBox(lua_State *L);
int w_GlyphData_getFormat(lua_State *L);
extern "C" int luaopen_glyphdata(lua_State *L);
} // font
+100
View File
@@ -32,8 +32,108 @@ Rasterizer *luax_checkrasterizer(lua_State *L, int idx)
return luax_checktype<Rasterizer>(L, idx, "Rasterizer", FONT_RASTERIZER_T);
}
int w_Rasterizer_getHeight(lua_State *L)
{
Rasterizer *t = luax_checkrasterizer(L, 1);
lua_pushinteger(L, t->getHeight());
return 1;
}
int w_Rasterizer_getAdvance(lua_State *L)
{
Rasterizer *t = luax_checkrasterizer(L, 1);
lua_pushinteger(L, t->getAdvance());
return 1;
}
int w_Rasterizer_getAscent(lua_State *L)
{
Rasterizer *t = luax_checkrasterizer(L, 1);
lua_pushinteger(L, t->getAscent());
return 1;
}
int w_Rasterizer_getDescent(lua_State *L)
{
Rasterizer *t = luax_checkrasterizer(L, 1);
lua_pushinteger(L, t->getDescent());
return 1;
}
int w_Rasterizer_getLineHeight(lua_State *L)
{
Rasterizer *t = luax_checkrasterizer(L, 1);
lua_pushinteger(L, t->getLineHeight());
return 1;
}
int w_Rasterizer_getGlyphData(lua_State *L)
{
Rasterizer *t = luax_checkrasterizer(L, 1);
GlyphData *g = 0;
try
{
// getGlyphData accepts a unicode character or a codepoint number.
if (lua_type(L, 2) == LUA_TSTRING)
{
std::string glyph = luax_checkstring(L, 2);
g = t->getGlyphData(glyph);
}
else
{
unsigned int glyph = (unsigned int) luaL_checknumber(L, 2);
g = t->getGlyphData(glyph);
}
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
luax_newtype(L, "GlyphData", FONT_GLYPH_DATA_T, (void *) g);
return 1;
}
int w_Rasterizer_getGlyphCount(lua_State *L)
{
Rasterizer *t = luax_checkrasterizer(L, 1);
lua_pushinteger(L, t->getGlyphCount());
return 1;
}
int w_Rasterizer_hasGlyph(lua_State *L)
{
Rasterizer *t = luax_checkrasterizer(L, 1);
bool hasglyph = false;
try
{
if (lua_type(L, 2) == LUA_TSTRING)
hasglyph = t->hasGlyph(luax_checkstring(L, 2));
else
hasglyph = t->hasGlyph((unsigned int) luaL_checknumber(L, 2));
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
luax_pushboolean(L, hasglyph);
return 1;
}
static const luaL_Reg functions[] =
{
{ "getHeight", w_Rasterizer_getHeight },
{ "getAdvance", w_Rasterizer_getAdvance },
{ "getAscent", w_Rasterizer_getAscent },
{ "getDescent", w_Rasterizer_getDescent },
{ "getLineHeight", w_Rasterizer_getLineHeight },
{ "getGlyphData", w_Rasterizer_getGlyphData },
{ "getGlyphCount", w_Rasterizer_getGlyphCount },
{ "hasGlyph", w_Rasterizer_hasGlyph },
{ 0, 0 }
};
+8
View File
@@ -31,6 +31,14 @@ namespace font
{
Rasterizer *luax_checkrasterizer(lua_State *L, int idx);
int w_Rasterizer_getHeight(lua_State *L);
int w_Rasterizer_getAdvance(lua_State *L);
int w_Rasterizer_getAscent(lua_State *L);
int w_Rasterizer_getDescent(lua_State *L);
int w_Rasterizer_getLineHeight(lua_State *L);
int w_Rasterizer_getGlyphData(lua_State *L);
int w_Rasterizer_getGlyphCount(lua_State *L);
int w_Rasterizer_hasGlyph(lua_State *L);
extern "C" int luaopen_rasterizer(lua_State *L);
} // font
+12 -2
View File
@@ -339,7 +339,7 @@ void Font::print(const std::string &text, float x, float y, float letter_spacing
catch (utf8::exception &e)
{
glPopMatrix();
throw love::Exception("%s", e.what());
throw love::Exception("Decoding error: %s", e.what());
}
if (quadindex > 0 && glyphinfolist.size() > 0)
@@ -399,7 +399,7 @@ int Font::getWidth(const std::string &str)
}
catch(utf8::exception &e)
{
throw love::Exception("%s", e.what());
throw love::Exception("Decoding error: %s", e.what());
}
if (width > max_width)
@@ -559,6 +559,16 @@ float Font::getBaseline() const
return (type == FONT_TRUETYPE) ? floor(getHeight() / 1.25f + 0.5f) : 0.0f;
}
bool Font::hasGlyph(unsigned int glyph) const
{
return rasterizer->hasGlyph(glyph);
}
bool Font::hasGlyph(const std::string &text) const
{
return rasterizer->hasGlyph(text);
}
} // opengl
} // graphics
} // love
+3
View File
@@ -138,6 +138,9 @@ public:
int getDescent() const;
float getBaseline() const;
bool hasGlyph(unsigned int glyph) const;
bool hasGlyph(const std::string &text) const;
private:
enum FontType
+22
View File
@@ -152,6 +152,27 @@ int w_Font_getBaseline(lua_State *L)
return 1;
}
int w_Font_hasGlyph(lua_State *L)
{
Font *t = luax_checkfont(L, 1);
bool hasglyph = false;
try
{
if (lua_type(L, 2) == LUA_TSTRING)
hasglyph = t->hasGlyph(luax_checkstring(L, 2));
else
hasglyph = t->hasGlyph((unsigned int) luaL_checknumber(L, 2));
}
catch (love::Exception &e)
{
return luaL_error(L, "%s", e.what());
}
luax_pushboolean(L, hasglyph);
return 1;
}
static const luaL_Reg functions[] =
{
{ "getHeight", w_Font_getHeight },
@@ -164,6 +185,7 @@ static const luaL_Reg functions[] =
{ "getAscent", w_Font_getAscent },
{ "getDescent", w_Font_getDescent },
{ "getBaseline", w_Font_getBaseline },
{ "hasGlyph", w_Font_hasGlyph },
{ 0, 0 }
};
+1
View File
@@ -43,6 +43,7 @@ int w_Font_getFilter(lua_State *L);
int w_Font_getAscent(lua_State *L);
int w_Font_getDescent(lua_State *L);
int w_Font_getBaseline(lua_State *L);
int w_Font_hasGlyph(lua_State *L);
extern "C" int luaopen_font(lua_State *L);
} // opengl
@@ -1150,9 +1150,9 @@ int w_print(lua_State *L)
{
instance->print(str, x, y, angle, sx, sy, ox, oy, kx,ky);
}
catch(love::Exception e)
catch(love::Exception &e)
{
return luaL_error(L, "Decoding error: %s", e.what());
return luaL_error(L, "%s", e.what());
}
return 0;
}
@@ -1193,9 +1193,9 @@ int w_printf(lua_State *L)
{
instance->printf(str, x, y, wrap, align, angle, sx, sy, ox, oy, kx, ky);
}
catch(love::Exception e)
catch(love::Exception &e)
{
return luaL_error(L, "Decoding error: %s", e.what());
return luaL_error(L, "%s", e.what());
}
return 0;
}