aboutsummaryrefslogtreecommitdiff
path: root/src/libjin/Graphics/Font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libjin/Graphics/Font.cpp')
-rw-r--r--src/libjin/Graphics/Font.cpp363
1 files changed, 0 insertions, 363 deletions
diff --git a/src/libjin/Graphics/Font.cpp b/src/libjin/Graphics/Font.cpp
deleted file mode 100644
index 9060961..0000000
--- a/src/libjin/Graphics/Font.cpp
+++ /dev/null
@@ -1,363 +0,0 @@
-#include "../jin_configuration.h"
-#if LIBJIN_MODULES_RENDER
-
-#include "OpenGL.h"
-#include "font.h"
-#include <stdio.h>
-#include "color.h"
-#include "Shader.h"
-#include "../Common/Array.hpp"
-
-namespace jin
-{
-namespace graphics
-{
-
- #include "Shaders/font.shader.h"
-
- using namespace std;
- using namespace jin::math;
-
- const int Font::TEXTURE_WIDTHS[] = { 128, 256, 256, 512, 512, 1024, 1024 };
- const int Font::TEXTURE_HEIGHTS[] = { 128, 128, 256, 256, 512, 512, 1024 };
-
- /* utf8 byte string to unicode codepoint */
- static const char* 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 {
- if (*(++p) == '\0') {
- *res = x;
- return p;
- }
- shift -= 6;
- x |= (*p & 0x3f) << shift;
- } while (shift);
- *res = x;
- return p + 1;
- }
-
- /* little endian unicode */
- static const char* unicodeLittleEndian(const char* p, unsigned* res)
- {
- }
-
- /*static*/ Font* Font::createFont(FontData* fontData, unsigned int fontSzie)
- {
- Font* font;
- try
- {
- font = new Font(fontData, fontSzie);
- }
- catch (...)
- {
- return nullptr;
- }
- return font;
- }
-
- Font::Font(FontData* f, unsigned int fontSize)
- : cursor(0, 0)
- , font(f)
- , fontsize(fontSize)
- {
- font->pushFontsize(fontsize);
- font->getVMetrics(&baseline, &descent);
- estimateSize();
- font->popFontsize();
- /* create a default texture */
- createAtlas();
- }
-
- /* estimate the size of atlas texture */
- void Font::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;
- }
- }
- }
-
- Font::~Font()
- {
- map<unsigned int, Glyph*>::iterator it = glyphs.begin();
- for (; it != glyphs.end(); ++it)
- {
- delete it->second;
- }
- }
-
- GLuint Font::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 Font::print(const char* t, int x, int y, int lineheight, int spacing)
- {
- Page* page = typeset(t, lineheight, spacing);
- print(page, x, y);
- delete page;
- }
-
- Page* Font::typeset(const char* text, int lineheight, int spacing)
- {
- // typesetting, for reducing draw call
- const char* t = text;
- Page* page = new Page();
- vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist;
- vector<GlyphVertex>& glyphvertices = page->glyphvertices;
- Vector2<int> p(0, 0);
- Codepoint c;
- int texture = -1;
- Glyph* glyph = nullptr;
- GlyphVertex vertex;
- for (int i = 0; *t != NULL; i += 4)
- {
- t = utf8toCodepoint(t, &c);
- if (c == 0x0D)
- {
- i -= 4;
- continue;
- }
- /* new line */
- if (c == 0x0A)
- {
- p.y += lineheight;
- p.x = 0;
- i -= 4;
- continue;
- }
- 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;
- Glyph::Bbox& bbox = glyph->bbox;
- // 1
- vertex.x = p.x; vertex.y = p.y;
- vertex.u = bbox.x; vertex.v = bbox.y;
- glyphvertices.push_back(vertex);
- // 2
- vertex.x = p.x; vertex.y = p.y + glyph->height;
- vertex.u = bbox.x; vertex.v = bbox.y + bbox.height;
- glyphvertices.push_back(vertex);
- // 3
- vertex.x = p.x + glyph->width; vertex.y = p.y + glyph->height;
- vertex.u = bbox.x + bbox.width; vertex.v = bbox.y + bbox.height;
- glyphvertices.push_back(vertex);
- // 4
- vertex.x = p.x + glyph->width; vertex.y = p.y;
- vertex.u = bbox.x + bbox.width; vertex.v = bbox.y;
- glyphvertices.push_back(vertex);
-
- p.x += glyph->width + spacing;
- }
- getTextBox(text, &page->width, &page->height, lineheight, spacing);
- return page;
- }
-
- void Font::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);
- }
- }
-
- int Font::getCharWidth(int c)
- {
- int adw, lsb;
- font->pushFontsize(fontsize);
- font->getHMetrics(c, &adw, &lsb);
- font->popFontsize();
- return adw;
- }
-
- int Font::getCharHeight(int c)
- {
- return descent;
- }
-
- int Font::getTextWidth(const char* t, int spacing)
- {
- font->pushFontsize(fontsize);
- int res = 0;
- int tmp = 0;
- const char *p = t;
- while (*p) {
- unsigned c;
- p = utf8toCodepoint(p, &c);
- if (*p == 0x0D)
- continue;
- if (*p == 0x0A)
- {
- tmp = 0;
- continue;
- }
- tmp += getCharWidth(c) + spacing;
- if (tmp > res) res = tmp;
- }
- font->popFontsize();
- return res;
- }
-
- int Font::getTextHeight(const char* t, int lineheight)
- {
- font->pushFontsize(fontsize);
- int res = 0;
- bool newline = true;
- while (*t)
- {
- unsigned c;
- t = utf8toCodepoint(t, &c);
- if (*t == 0x0A)
- newline = true;
- else if (*t == 0x0D);
- else if (newline)
- {
- newline = false;
- res += lineheight;
- }
- }
- font->popFontsize();
- return res;
- }
-
- void Font::getTextBox(const char* text, int* w, int* h, int lineheight, int spacing)
- {
- font->pushFontsize(fontsize);
- *w = 0;
- *h = 0;
- int tmp = 0;
- const char* p = text;
- const char* pt = nullptr;
- bool nl = true;
- while (*p) {
- unsigned c;
- pt = p;
- p = utf8toCodepoint(p, &c);
- if (*pt == 0x0D)
- continue;
- if (*pt == 0x0A)
- {
- tmp = 0;
- nl = true;
- continue;
- }
- else if(nl)
- {
- nl = false;
- *h += lineheight;
- }
- tmp += getCharWidth(c) + spacing;
- if (tmp > *w) *w = tmp;
- }
- font->popFontsize();
- }
-
- Glyph* Font::bakeGlyph(unsigned int character)
- {
- Glyph* glyph = (Glyph*)malloc(sizeof(Glyph));
- int w, h, xoff, yoff;
- font->pushFontsize(fontsize);
- GLuint atlas = atlases.back();
- const Color* bitmap = font->getCodepointBitmap(character, &w, &h, &xoff, &yoff);
- int adw, lsb;
- {
- font->getHMetrics(character, &adw, &lsb);
- font->popFontsize();
- 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;
- }
- glyph->atlas = atlas;
- glyph->bbox.x = cursor.x / (float)textureWidth;
- glyph->bbox.y = cursor.y / (float)textureHeight;
- glyph->bbox.width = adw / (float)textureWidth;
- glyph->bbox.height = descent / (float)textureHeight;
- glyph->width = adw;
- glyph->height = descent;
- glyphs.insert(std::pair<unsigned int, Glyph*>(character, glyph));
-
- cursor.x += adw;
- return glyph;
- }
-
- Glyph* Font::findGlyph(unsigned int character)
- {
- map<unsigned int, Glyph*>::iterator it = glyphs.find(character);
- if (it != glyphs.end())
- {
- return it->second;
- }
- else
- {
- Glyph* glyph = bakeGlyph(character);
- return glyph;
- }
- }
-
-} // graphics
-} // jin
-
-#endif // LIBJIN_MODULES_RENDER \ No newline at end of file