diff options
Diffstat (limited to 'src/libjin/Graphics/Font.cpp')
-rw-r--r-- | src/libjin/Graphics/Font.cpp | 217 |
1 files changed, 81 insertions, 136 deletions
diff --git a/src/libjin/Graphics/Font.cpp b/src/libjin/Graphics/Font.cpp index b95f78b..bb767db 100644 --- a/src/libjin/Graphics/Font.cpp +++ b/src/libjin/Graphics/Font.cpp @@ -12,166 +12,111 @@ namespace jin namespace graphics { + using namespace std; using namespace jin::math; - const int BITMAP_WIDTH = 512; - const int BITMAP_HEIGHT = 512; - const int PIXEL_HEIGHT = 32; + const int Font::TEXTURE_WIDTHS[] = { 128, 256, 256, 512, 512, 1024, 1024 }; + const int Font::TEXTURE_HEIGHTS[] = { 128, 128, 256, 256, 512, 512, 1024 }; + + static const char *ttf_utf8toCodepoint(const char *p, unsigned *res) { + unsigned x, mask, shift; + switch (*p & 0xf0) { + case 0xf0: mask = 0x07; shift = 18; break; + case 0xe0: mask = 0x0f; shift = 12; break; + case 0xc0: + case 0xd0: mask = 0x1f; shift = 6; break; + default: + *res = *p; + return p + 1; + } + x = (*p & mask) << shift; + do { + /* Return early if we reach an unexpected NULL */ + if (*(++p) == '\0') { + *res = x; + return p; + } + shift -= 6; + x |= (*p & 0x3f) << shift; + } while (shift); + *res = x; + return p + 1; + } - Font::Font():Drawable() + /*static*/ Font* Font::createFont(const char* font, size_t size) { + } - // ttf file read buffer - static unsigned char ttf_buffer[1 << 20]; + /*static*/ Font* Font::createFont(const char* file) + { - // bitmap for saving font data - static unsigned char temp_bitmap[BITMAP_WIDTH * BITMAP_HEIGHT]; + } - void Font::loadFile(const char* path) + Font::Font() + : textureLevel(TEXTURE_SIZE_LEVEL_MAX) { - fread(ttf_buffer, 1, 1 << 20, fopen(path, "rb")); - loadMemory(ttf_buffer); + } - /** - * load from memory - */ - void Font::loadMemory(const unsigned char* data) + bool Font::createTexture() { - if (data == nullptr) - return; - - stbtt_BakeFontBitmap(data, 0, PIXEL_HEIGHT, temp_bitmap, BITMAP_WIDTH, BITMAP_HEIGHT, 32, ASCII_CHARACTER_NUM, asciiData); - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, BITMAP_WIDTH, BITMAP_HEIGHT, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + GLuint t; + glGenTextures(1, &t); + glBindTexture(GL_TEXTURE_2D, t); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_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); + /*Initialize the texture, attempting smaller sizes if initialization fails.*/ + bool initialized = false; + while (textureLevel >= 0) + { + /*clear errors before initializing*/ + while (glGetError() != GL_NO_ERROR); + textureWidth = TEXTURE_WIDTHS[textureLevel]; + textureHeight = TEXTURE_HEIGHTS[textureLevel]; + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, textureWidth, textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + initialized = (glGetError() == GL_NO_ERROR); + if (initialized || textureLevel <= 0) + break; + --textureLevel; + } + if (!initialized) + { + glDeleteTextures(1, &t); + glBindTexture(GL_TEXTURE_2D, 0); + return false; + } + textures.push_back(t); glBindTexture(GL_TEXTURE_2D, 0); + return true; } - /** - * get texture quad - */ - static Quad getCharQuad(const stbtt_bakedchar* chardata, int pw, int ph, int char_index) + void Font::print(const char* text, int x, int y) { - float ipw = 1.0f / pw, iph = 1.0f / ph; - const stbtt_bakedchar *b = chardata + char_index; - Quad q; - q.x = b->x0 * ipw; - q.y = b->y0 * iph; - q.w = b->x1 * ipw - b->x0 * ipw; - q.h = b->y1 * iph - b->y0 * iph; - return q; + int len = strlen(text); + /* xy and uv list */ + vector<GlyphVertex> glyphvertices(len*4); + /* texture binded along with glyphvertices */ + vector<GlyphArrayDrawInfo> glyphinfolist; + float dx = 0; + float dy = 0; + //float lineheihgt = ; } - void Font::render( - const char* text, - float x, float y, - int fontHeight, - int spacing, - int lineHeight) + /** + * unicodeȾļtextureϣglyphs + */ + Glyph* Font::addGlyph(unsigned int character) { - float _x = x, - _y = y; + GLuint texture = textures.back(); - int len = strlen(text); - - glBindTexture(GL_TEXTURE_2D, texture); - - // for saving clip quad - stbtt_aligned_quad q; - - // render every given character - float xc = x; - float yc = y; - - float factor = fontHeight / (float)PIXEL_HEIGHT; - float texCoord[8]; - float verCoord[8]; - for (int i = 0; i < len; ++i) - { - char c = text[i]; - if (c == '\n') - { - xc = x; - yc += lineHeight; - continue; - } - - // only support ASCII - Quad q = getCharQuad(asciiData, 512, 512, c - 32); - float s0 = q.x, - s1 = q.x + q.w, - t0 = q.y, - t1 = q.y + q.h; - - // texture quad - texCoord[0] = s0; texCoord[1] = t1; - texCoord[2] = s1; texCoord[3] = t1; - texCoord[4] = s1; texCoord[5] = t0; - texCoord[6] = s0; texCoord[7] = t0; - - // character bound box - stbtt_bakedchar box = asciiData[c - 32]; - - float width = factor * (box.x1 - box.x0); - float height = factor * (box.y1 - box.y0); - float xoffset = factor * box.xoff; - // I don't know why add PIXEL_HEIGHT to box.yoff, but - // it works. - float yoffset = factor * (box.yoff + PIXEL_HEIGHT); - float xadvance = factor * box.xadvance; - - // render quad - verCoord[0] = xc + xoffset; verCoord[1] = yc + height + yoffset; - verCoord[2] = xc + width + xoffset; verCoord[3] = yc + height + yoffset; - verCoord[4] = xc + width + xoffset; verCoord[5] = yc + yoffset; - verCoord[6] = xc + xoffset; verCoord[7] = yc + yoffset; - - // forward to next character - xc += xadvance + spacing; - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glTexCoordPointer(2, GL_FLOAT, 0, texCoord); - glVertexPointer(2, GL_FLOAT, 0, verCoord); - glDrawArrays(GL_QUADS, 0, 4); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - } - - glBindTexture(GL_TEXTURE_2D, 0); } - void Font::box(const char* text, int fontHeight, int spacing, int lineHeight, int* w, int * h) + Glyph* Font::findGlyph(unsigned int character) { - int len = strlen(text); - - float xc = 0; - int yc = len ? lineHeight : 0; - int maxX = 0; - - float factor = fontHeight / (float)PIXEL_HEIGHT; - - for (int i = 0; i < len; ++i) - { - char c = text[i]; - if (c == '\n') - { - yc += lineHeight; - xc = 0; - continue; - } - stbtt_bakedchar box = asciiData[c - 32]; - - xc += factor * box.xadvance + spacing; - if (xc > maxX) maxX = xc; - } - *w = maxX; - *h = yc; } } // graphics |