diff options
Diffstat (limited to 'src/libjin/Graphics/Font/je_ttf.cpp')
-rw-r--r-- | src/libjin/Graphics/Font/je_ttf.cpp | 463 |
1 files changed, 0 insertions, 463 deletions
diff --git a/src/libjin/Graphics/Font/je_ttf.cpp b/src/libjin/Graphics/Font/je_ttf.cpp deleted file mode 100644 index a11efb0..0000000 --- a/src/libjin/Graphics/Font/je_ttf.cpp +++ /dev/null @@ -1,463 +0,0 @@ -#include "../../core/je_configuration.h" -#if defined(jin_graphics) - -#include <stdio.h> - -#include "../../common/je_array.hpp" - -#include "../je_gl.h" -#include "../je_color.h" -#include "../shader/je_shader.h" - -#include "je_ttf.h" -#include "je_page.h" - -#define STB_TRUETYPE_IMPLEMENTATION -#include "../../3rdparty/stb/stb_truetype.h" - -namespace JinEngine -{ - namespace Graphics - { - - ///////////////////////////////////////////////////////////////////////////// - // TTFData - ///////////////////////////////////////////////////////////////////////////// - - TTFData* TTFData::createTTFData(const unsigned char* data, unsigned int size) - { - TTFData* ttf = nullptr; - try - { - ttf = new TTFData(data, size); - return ttf; - } - catch (...) - { - return nullptr; - } - } - - TTFData::TTFData(const unsigned char* d, unsigned int s) - { - raw.size = s; - raw.data = (unsigned char*)malloc(s); - memcpy(raw.data, d, s); - if (!stbtt_InitFont(&info, (const unsigned char*)raw.data, 0)) - { - delete raw.data; - throw 0; - } - /* push default fontsize */ - pushTTFsize(FONT_SIZE); - } - - TTFData::~TTFData() - { - free(raw.data); - } - - TTF* TTFData::createTTF(unsigned fontSize) - { - TTF* ttf; - try - { - ttf = new TTF(this, fontSize); - } - catch (...) - { - return nullptr; - } - return ttf; - } - - /* - * (0, 0) - * +--------------+ ascent - * | +--------+ | - * | | | | - * | | bitmap | | - * +--|--------|--+ baseline - * | +--------+ | - * +--|-----------+ decent - * | | - * leftSideBearing | - * advanceWidth - */ - void TTFData::getVMetrics(int* baseline, int* descent) - { - float scale = scales.back(); - int ascent; - stbtt_GetFontVMetrics(&info, &ascent, descent, 0); - *baseline = (int)(ascent*scale) + 1; // slight adjustment - *descent = *baseline - (int)(*descent*scale) + 1; - } - - void TTFData::getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing) - { - float scale = scales.back(); - int adw, lsb; - stbtt_GetCodepointHMetrics(&info, codepoint, &adw, &lsb); - *advanceWidth = (int)(adw*scale); - *leftSideBearing = (int)(lsb*scale); - } - - void TTFData::pushTTFsize(unsigned int fs) - { - float sc = stbtt_ScaleForPixelHeight(&info, fs); - scales.push_back(sc); - } - - void TTFData::popTTFsize() - { - /* always keep default ttf size on the bottom of stack */ - if (scales.size() > 1) - scales.pop_back(); - } - - Channel* TTFData::getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const - { - float scale = scales.back(); - Channel* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, codepoint, width, height, xoff, yoff); - return bitmap; - } - - Color* TTFData::getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const - { - float scale = scales.back(); - Channel* bitmap = stbtt_GetCodepointBitmap(&info, scale, scale, codepoint, width, height, xoff, yoff); - int w = *width, h = *height; - //int xo = *xoff, yo = *yoff; - Color* bitmap32 = new Color[w*h]; - for (int y = 0; y < h; ++y) - { - for (int x = 0; x < w; ++x) - { - bitmap32[x + y * w].set(0xff, 0xff, 0xff, bitmap[x + y * w]); - } - } - free(bitmap); - return bitmap32; - } - - ///////////////////////////////////////////////////////////////////////////// - // TTF - ///////////////////////////////////////////////////////////////////////////// - - #include "../shader/je_font.shader.h" - - using namespace std; - using namespace JinEngine::Math; - - const int TTF::TEXTURE_WIDTHS[] = { 128, 256, 256, 512, 512, 1024, 1024 }; - const int TTF::TEXTURE_HEIGHTS[] = { 128, 128, 256, 256, 512, 512, 1024 }; - - /* little endian unicode */ - static const char* unicodeLittleEndian(const char* p, unsigned* res) - { - } - - ///*static*/ TTF* TTF::createTTF(TTFData* fontData, unsigned int fontSzie) - //{ - // TTF* ttf; - // try - // { - // ttf = new TTF(fontData, fontSzie); - // } - // catch (...) - // { - // return nullptr; - // } - // return ttf; - //} - - TTF::TTF(TTFData* f, unsigned int fontSize) - : Font(fontSize) - , cursor(0, 0) - , ttf(f) - { - ttf->pushTTFsize(fontSize); - ttf->getVMetrics(&baseline, &descent); - estimateSize(); - ttf->popTTFsize(); - /* create a default texture */ - createAtlas(); - } - - /* estimate the size of atlas texture */ - void TTF::estimateSize() - { - for (int level = 0; level <= TEXTURE_SIZE_LEVEL_MAX; ++level) - { - if (descent * (descent*0.8) * 96 <= TEXTURE_WIDTHS[level] * TEXTURE_HEIGHTS[level]) - { - textureWidth = TEXTURE_WIDTHS[level]; - textureHeight = TEXTURE_HEIGHTS[level]; - break; - } - } - } - - TTF::~TTF() - { - } - - GLuint TTF::createAtlas() - { - GLuint t; - gl.flushError(); - t = gl.genTexture(); - gl.bindTexture(t); - gl.setTexParameter(GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gl.setTexParameter(GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gl.setTexParameter(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl.setTexParameter(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - gl.texImage(GL_RGBA8, textureWidth, textureHeight, GL_RGBA, GL_UNSIGNED_BYTE); - if (glGetError() != GL_NO_ERROR) - { - glDeleteTextures(1, &t); - gl.bindTexture(0); - return 0; - } - atlases.push_back(t); - gl.bindTexture(0); - return t; - } - - void TTF::print(const Content& t, int x, int y, int lineheight, int spacing) - { - Page* page = typeset(t, lineheight, spacing); - print(page, x, y); - delete page; - } - - Page* TTF::typeset(const Content& text, int lineheight, int spacing) - { - Page* page = new Page(); - page->font = this; - vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist; - vector<GlyphVertex>& glyphvertices = page->glyphvertices; - int texture = -1; - TTFGlyph* glyph = nullptr; - GlyphVertex vertex; - Vector2<int> p(0, 0); - int i = 0; - - #define glyphvertices_push(_x, _y, _u, _v) \ - vertex.x = _x; vertex.y = _y;\ - vertex.u = _u; vertex.v = _v;\ - glyphvertices.push_back(vertex); - - #define glyphlize(c)\ - do{\ - glyph = &findGlyph(c); \ - if (texture != glyph->atlas) \ - { \ - GlyphArrayDrawInfo info; \ - info.start = i; \ - info.count = 0; \ - info.texture = glyph->atlas; \ - texture = glyph->atlas; \ - glyphinfolist.push_back(info); \ - } \ - glyphinfolist[glyphinfolist.size() - 1].count += 4; \ - TTFGlyph::Bbox& bbox = glyph->bbox; \ - glyphvertices_push(p.x, p.y, bbox.x, bbox.y); \ - glyphvertices_push(p.x, p.y + glyph->height, bbox.x, bbox.y + bbox.h); \ - glyphvertices_push(p.x + glyph->width, p.y + glyph->height, bbox.x + bbox.w, bbox.y + bbox.h); \ - glyphvertices_push(p.x + glyph->width, p.y, bbox.x + bbox.w, bbox.y); \ - }while(0) - - for (Codepoint c : text) - { - if (c == 0x0D) - continue; - if (c == 0x0A) - { - /* new line */ - p.y += lineheight; - p.x = 0; - continue; - } - if (c == 0x09) - { - // tab = 4*space - unsigned cw = getCharWidth(0x20); - p.x += cw * 4; - continue; - } - glyphlize(c); - p.x += glyph->width + spacing; - i += 4; - } - getTextBox(text, &page->size.w, &page->size.h, lineheight, spacing); - return page; - } - - Page* TTF::typeset(const Text& text, int lineheight, int spacing) - { - return typeset(*text, lineheight, spacing); - } - - void TTF::print(const Page* page, int x, int y) - { - Shader* shader = Shader::getCurrentShader(); - const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist; - const vector<GlyphVertex>& glyphvertices = page->glyphvertices; - gl.ModelMatrix.setTransformation(x, y, 0, 1, 1, 0, 0); - shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix); - shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix); - for (int i = 0; i < glyphinfolist.size(); ++i) - { - const GlyphArrayDrawInfo& info = glyphinfolist[i]; - shader->bindVertexPointer(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x); - shader->bindUVPointer(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u); - gl.bindTexture(info.texture); - gl.drawArrays(GL_QUADS, 0, info.count); - gl.bindTexture(0); - } - } - - void TTF::print(const Text& text, int x, int y, int lineheight, int spacing /* = 0 */) - { - print(*text, x, y, lineheight, spacing); - } - - int TTF::getCharWidth(int c) - { - int adw, lsb; - ttf->pushTTFsize(mFontSize); - ttf->getHMetrics(c, &adw, &lsb); - ttf->popTTFsize(); - return adw; - } - - int TTF::getCharHeight(int c) - { - return descent; - } - - int TTF::getTextWidth(const Content& t, int spacing) - { - ttf->pushTTFsize(mFontSize); - int res = 0; - int tmp = 0; - for (Codepoint c : t) - { - if (c == 0x0D) - continue; - if (c == 0x0A) - { - tmp = 0; - continue; - } - tmp += getCharWidth(c) + spacing; - if (tmp > res) - res = tmp; - } - ttf->popTTFsize(); - return res; - } - - int TTF::getTextHeight(const Content& t, int lineheight) - { - ttf->pushTTFsize(mFontSize); - int res = 0; - bool newline = true; - for (Codepoint c : t) - { - if (c == 0x0A) - newline = true; - else if (c == 0x0D); - else if (newline) - { - newline = false; - res += lineheight; - } - } - ttf->popTTFsize(); - return res; - } - - void TTF::getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing) - { - ttf->pushTTFsize(mFontSize); - *w = 0; - *h = 0; - int tmp = 0; - bool newline = true; - for (Codepoint c : text) - { - if (c == 0x0D) - continue; - if (c == 0x0A) - { - tmp = 0; - newline = true; - continue; - } - else if (newline) - { - newline = false; - *h += lineheight; - } - tmp += getCharWidth(c) + spacing; - if (tmp > *w) - *w = tmp; - } - ttf->popTTFsize(); - } - - TTF::TTFGlyph& TTF::bakeGlyph(unsigned int character) - { - int w, h, xoff, yoff; - ttf->pushTTFsize(mFontSize); - GLuint atlas = atlases.back(); - const Color* bitmap = ttf->getCodepointBitmap(character, &w, &h, &xoff, &yoff); - int adw, lsb; - { - /* bake glyph */ - ttf->getHMetrics(character, &adw, &lsb); - ttf->popTTFsize(); - if (cursor.x + adw > textureWidth ) - { - cursor.x = 0; - cursor.y += descent; - if (cursor.y + descent * 2 > textureHeight) - { - /* create new atlas */ - atlas = createAtlas(); - cursor.y = 0; - } - } - gl.bindTexture(atlas); - gl.texSubImage(cursor.x + xoff, cursor.y + yoff + baseline, w, h, GL_RGBA, GL_UNSIGNED_BYTE, bitmap); - gl.bindTexture(); - delete[] bitmap; - } - TTFGlyph glyph; - glyph.atlas = atlas; - glyph.bbox.x = cursor.x / (float)textureWidth; - glyph.bbox.y = cursor.y / (float)textureHeight; - glyph.bbox.w = adw / (float)textureWidth; - glyph.bbox.h = descent / (float)textureHeight; - glyph.width = adw; - glyph.height = descent; - glyphs.insert(std::pair<unsigned int, TTFGlyph>(character, glyph)); - cursor.x += adw; - return glyphs[character]; - } - - TTF::TTFGlyph& TTF::findGlyph(unsigned int character) - { - map<unsigned int, TTFGlyph>::iterator it = glyphs.find(character); - if (it != glyphs.end()) - return it->second; - else - return bakeGlyph(character); - } - - } // namespace Graphics -} // namespace JinEngine - -#endif // defined(jin_graphics)
\ No newline at end of file |