GlyphData *BMFontRasterizer::getGlyphData(uint32 glyph) const { auto it = characters.find(glyph); // Return an empty GlyphData if we don't have the glyph character. if (it == characters.end()) return new GlyphData(glyph, GlyphMetrics(), GlyphData::FORMAT_RGBA); const BMFontCharacter &c = it->second; GlyphData *g = new GlyphData(glyph, c.metrics, GlyphData::FORMAT_RGBA); const auto &imagepair = images.find(c.page); if (imagepair == images.end()) { g->release(); return new GlyphData(glyph, GlyphMetrics(), GlyphData::FORMAT_RGBA); } image::ImageData *imagedata = imagepair->second.get(); image::pixel *pixels = (image::pixel *) g->getData(); const image::pixel *ipixels = (const image::pixel *) imagedata->getData(); love::thread::Lock lock(imagedata->getMutex()); // Copy the subsection of the texture from the ImageData to the GlyphData. for (int y = 0; y < c.metrics.height; y++) { size_t idindex = (c.y + y) * imagedata->getWidth() + c.x; memcpy(&pixels[y * c.metrics.width], &ipixels[idindex], sizeof(image::pixel) * c.metrics.width); } return g; }
int w_GlyphData_getGlyph(lua_State *L) { GlyphData *t = luax_checkglyphdata(L, 1); uint32 glyph = t->getGlyph(); lua_pushnumber(L, (lua_Number) glyph); 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_getGlyphString(lua_State *L) { GlyphData *t = luax_checkglyphdata(L, 1); luax_catchexcept(L, [&](){ luax_pushstring(L, t->getGlyphString()); }); 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; }
GlyphData Font::getGlyphDataFromChar(unsigned long c) { FT_Load_Char(*m_face, c, FT_LOAD_DEFAULT | FT_LOAD_RENDER); GlyphData g; g.initFromFace(m_face, c); return g; }
void FontTexture::upload(const GlyphData &glyphData) { if (!glId && glyphData.isValid()) { auto glyphWidth = glyphData.width; auto glyphHeight = glyphData.height; auto glyphPadding = glyphData.padding; auto buffer = glyphData.getBuffer(); useMipmap = glyphData.useMipmap; width = utils::math::nextPowerOfTwo(glyphWidth + glyphPadding * 2); height = utils::math::nextPowerOfTwo(glyphHeight + glyphPadding * 2); auto data = new unsigned char[width * height](); // ZERO-FILLED for (int y = 0; y < glyphHeight; y++) { for (int x = 0; x < glyphWidth; x++) { data[(y + glyphPadding) * width + (x + glyphPadding)] = buffer[y * glyphWidth + x]; } } // --- glGenTextures(1, &glId); glBindTexture(GL_TEXTURE_2D, glId); if (useMipmap) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (useMipmap) { glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); } glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data); if (useMipmap) { glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); } glBindTexture(GL_TEXTURE_2D, 0); delete[] data; } }
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; }
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_newGlyphData(lua_State *L) { Rasterizer *r = luax_checkrasterizer(L, 1); GlyphData *t = nullptr; // newGlyphData accepts a unicode character or a codepoint number. if (lua_type(L, 2) == LUA_TSTRING) { std::string glyph = luax_checkstring(L, 2); luax_catchexcept(L, [&](){ t = instance()->newGlyphData(r, glyph); }); } else { uint32 g = (uint32) luaL_checknumber(L, 2); t = instance()->newGlyphData(r, g); } luax_pushtype(L, FONT_GLYPH_DATA_ID, t); t->release(); return 1; }
GlyphData * ImageRasterizer::getGlyphData(unsigned short glyph) const { GlyphMetrics gm; gm.height = metrics.height; gm.width = widths[glyph]; gm.advance = spacing[glyph] + widths[glyph]; gm.bearingX = 0; gm.bearingY = 0; GlyphData * g = new GlyphData(glyph, gm, GlyphData::FORMAT_RGBA); if (gm.width == 0) return g; unsigned char * gd = (unsigned char*)g->getData(); love::image::pixel * pixels = (love::image::pixel *)(imageData->getData()); for (unsigned int i = 0; i < widths[glyph]*getHeight(); i++) { love::image::pixel p = pixels[ positions[glyph] + (i % widths[glyph]) + (imageData->getWidth() * (i / widths[glyph])) ]; gd[i*4] = p.r; gd[i*4+1] = p.g; gd[i*4+2] = p.b; gd[i*4+3] = p.a; } return g; }
GlyphData *ImageRasterizer::getGlyphData(uint32 glyph) const { GlyphMetrics gm = {}; // Set relevant glyph metrics if the glyph is in this ImageFont std::map<uint32, ImageGlyphData>::const_iterator it = imageGlyphs.find(glyph); if (it != imageGlyphs.end()) { gm.width = it->second.width; gm.advance = it->second.width + extraSpacing; } gm.height = metrics.height; GlyphData *g = new GlyphData(glyph, gm, GlyphData::FORMAT_RGBA); if (gm.width == 0) return g; // We don't want another thread modifying our ImageData mid-copy. love::thread::Lock lock(imageData->getMutex()); love::image::pixel *gdpixels = (love::image::pixel *) g->getData(); love::image::pixel *imagepixels = (love::image::pixel *) imageData->getData(); // copy glyph pixels from imagedata to glyphdata for (int i = 0; i < g->getWidth() * g->getHeight(); i++) { love::image::pixel p = imagepixels[it->second.x + (i % gm.width) + (imageData->getWidth() * (i / gm.width))]; // Use transparency instead of the spacer color if (equal(p, spacer)) gdpixels[i].r = gdpixels[i].g = gdpixels[i].b = gdpixels[i].a = 0; else gdpixels[i] = p; } return g; }
int w_GlyphData_getAdvance(lua_State *L) { GlyphData *t = luax_checkglyphdata(L, 1); lua_pushinteger(L, t->getAdvance()); return 1; }