diff options
author | chai <chaifix@163.com> | 2018-09-12 21:04:12 +0800 |
---|---|---|
committer | chai <chaifix@163.com> | 2018-09-12 21:04:12 +0800 |
commit | 846d6ab0ec1033481574e8324a43fc547ecf5882 (patch) | |
tree | 14f51d552855dccd24a619742b8ae58c883a79e7 /src | |
parent | 0ea853c2aad2aa3670eb694328743bb806e603bf (diff) |
*update
Diffstat (limited to 'src')
-rw-r--r-- | src/libjin/Graphics/Font.cpp | 217 | ||||
-rw-r--r-- | src/libjin/Graphics/Font.h | 79 | ||||
-rw-r--r-- | src/libjin/Graphics/Shader.cpp | 2 |
3 files changed, 141 insertions, 157 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 diff --git a/src/libjin/Graphics/Font.h b/src/libjin/Graphics/Font.h index 0ab482d..10fd242 100644 --- a/src/libjin/Graphics/Font.h +++ b/src/libjin/Graphics/Font.h @@ -3,6 +3,8 @@ #include "../modules.h" #if LIBJIN_MODULES_RENDER +#include <vector> +#include <map> #include "drawable.h" #include "../3rdparty/stb/stb_truetype.h" #include "../math/quad.h" @@ -11,33 +13,68 @@ namespace jin { namespace graphics { + /** + * original from love2d font and graphics modules + * the basic idea is storing glyphs in several mipmap + * http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html + */ - class Font: public Drawable + struct GlyphVertex + { + float x, y; // screen coordinates + float u, v; // texture coordinates + }; + + /* track when to change texutre binded in render array */ + /* casue switch texture is expensive */ + /* std::vector<GlyphVertex> list */ + struct GlyphArrayDrawInfo + { + GLuint texture; + int startvertex; + int vertexcount; + }; + + /* glyph texture */ + struct Glyph + { + GLuint texture; // texture where this glyph rendered + int spacing; // spacing of glyph + GlyphVertex vertices[4]; // quad of glyph render region + }; + + class Font { public: - Font * createFont(const char* file); - Font* createFont(const char* data, size_t size); + static Font* createFont(const char* file); + static Font* createFont(const char* data, size_t size); - void box(const char* text, int fontHeight, int spacing, int lineHeight, int* w, int * h); + void print(const char* text, int x, int y); private: - /* ASCII 32(space)..126(~) 95 glyphs */ - static const int ASCII_CHARACTER_NUM = 96; - - Font(); - - void loadFile(const char* file); - void loadMemory(const unsigned char* data); - void render( - const char* text, // rendered text - float x, float y, // render position - int fondSize, // font size - int spacing, // font spacing - int lineHeight // line height - ); - - stbtt_bakedchar asciiData[ASCII_CHARACTER_NUM]; - + /* font atlas levels */ + static const int TEXTURE_SIZE_LEVELS_COUNT = 7; + static const int TEXTURE_SIZE_LEVEL_MAX = TEXTURE_SIZE_LEVELS_COUNT - 1; + static const int TEXTURE_WIDTHS[TEXTURE_SIZE_LEVELS_COUNT]; + static const int TEXTURE_HEIGHTS[TEXTURE_SIZE_LEVELS_COUNT]; + static const int SPACES_PER_TAB = 4; + + /* create a new mipmap to render glyph and push it on textures */ + bool createTexture(); + /* create a glyph for a unicode and return it */ + Glyph* addGlyph(unsigned int character); + /* find glyph by unicode */ + Glyph* findGlyph(unsigned int character); + + /* list of textures where glyphs rendered, always operate the last one */ + /* map character to its render area */ + std::vector<GLuint> textures; + std::map<unsigned int, Glyph*> glyphs; + /* mipmap size level */ + int textureLevel; + int textureWidth; + int textureHeight; + }; } // graphics diff --git a/src/libjin/Graphics/Shader.cpp b/src/libjin/Graphics/Shader.cpp index 12d4db0..e882d35 100644 --- a/src/libjin/Graphics/Shader.cpp +++ b/src/libjin/Graphics/Shader.cpp @@ -160,6 +160,7 @@ namespace graphics glUniform1i(location, unit); glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, tex->getTexture()); + glActiveTexture(GL_TEXTURE0); } @@ -178,6 +179,7 @@ namespace graphics glUniform1i(location, unit); glActiveTexture(GL_TEXTURE0 + unit); glBindTexture(GL_TEXTURE_2D, canvas->getTexture()); + glActiveTexture(GL_TEXTURE0); } |