aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-09-12 21:04:12 +0800
committerchai <chaifix@163.com>2018-09-12 21:04:12 +0800
commit846d6ab0ec1033481574e8324a43fc547ecf5882 (patch)
tree14f51d552855dccd24a619742b8ae58c883a79e7 /src
parent0ea853c2aad2aa3670eb694328743bb806e603bf (diff)
*update
Diffstat (limited to 'src')
-rw-r--r--src/libjin/Graphics/Font.cpp217
-rw-r--r--src/libjin/Graphics/Font.h79
-rw-r--r--src/libjin/Graphics/Shader.cpp2
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);
}