aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-10-14 22:52:40 +0800
committerchai <chaifix@163.com>2018-10-14 22:52:40 +0800
commitb1bbc998960fff2169dc5a992c47d08723472f9b (patch)
tree220f3bd5de2266e248884e11161dd715d7632ef2 /src
parentfbf989f9950a38566e0fb0fc5b6a7aebc9f0fb45 (diff)
*直接渲染字符串
Diffstat (limited to 'src')
-rw-r--r--src/libjin/Common/Exception.cpp0
-rw-r--r--src/libjin/Common/Exception.h0
-rw-r--r--src/libjin/Filesystem/Filesystem.cpp2
-rw-r--r--src/libjin/Game/Game.cpp1
-rw-r--r--src/libjin/Graphics/Bitmap.h6
-rw-r--r--src/libjin/Graphics/Color.h6
-rw-r--r--src/libjin/Graphics/Drawable.cpp61
-rw-r--r--src/libjin/Graphics/Drawable.h6
-rw-r--r--src/libjin/Graphics/Font.cpp363
-rw-r--r--src/libjin/Graphics/Font.h104
-rw-r--r--src/libjin/Graphics/Font/Decoder.cpp93
-rw-r--r--src/libjin/Graphics/Font/Decoder.h44
-rw-r--r--src/libjin/Graphics/Font/Font.h31
-rw-r--r--src/libjin/Graphics/Font/Page.h38
-rw-r--r--src/libjin/Graphics/Font/TTF.cpp463
-rw-r--r--src/libjin/Graphics/Font/TTF.h127
-rw-r--r--src/libjin/Graphics/Font/Text.cpp151
-rw-r--r--src/libjin/Graphics/Font/Text.h74
-rw-r--r--src/libjin/Graphics/Font/TextureFont.cpp300
-rw-r--r--src/libjin/Graphics/Font/TextureFont.h62
-rw-r--r--src/libjin/Graphics/FontData.cpp115
-rw-r--r--src/libjin/Graphics/FontData.h45
-rw-r--r--src/libjin/Graphics/Graphics.h6
-rw-r--r--src/libjin/Graphics/Image.cpp34
-rw-r--r--src/libjin/Graphics/Image.h33
-rw-r--r--src/libjin/Graphics/Particles/Particle.cpp0
-rw-r--r--src/libjin/Graphics/Particles/Particle.h0
-rw-r--r--src/libjin/Graphics/Shaders/base.shader.h30
-rw-r--r--src/libjin/Graphics/Sprite.cpp0
-rw-r--r--src/libjin/Graphics/Sprite.h18
-rw-r--r--src/libjin/Graphics/Texture.cpp12
-rw-r--r--src/libjin/Graphics/Utf8.cpp68
-rw-r--r--src/libjin/Graphics/Utf8.h44
-rw-r--r--src/libjin/Math/Vector2.hpp5
-rw-r--r--src/libjin/Math/Vector4.hpp1
-rw-r--r--src/lua/common/Proxy.h12
-rw-r--r--src/lua/common/Reference.hpp12
-rw-r--r--src/lua/embed/graphics.lua.h3
-rw-r--r--src/lua/libraries/luax/luax.h1
-rw-r--r--src/lua/modules/graphics/bitmap.cpp4
-rw-r--r--src/lua/modules/graphics/font.cpp79
-rw-r--r--src/lua/modules/graphics/fontData.cpp45
-rw-r--r--src/lua/modules/graphics/graphics.cpp314
-rw-r--r--src/lua/modules/graphics/page.cpp18
-rw-r--r--src/lua/modules/graphics/text.cpp32
-rw-r--r--src/lua/modules/graphics/textureFont.cpp67
-rw-r--r--src/lua/modules/graphics/ttf.cpp73
-rw-r--r--src/lua/modules/graphics/ttfData.cpp51
-rw-r--r--src/lua/modules/types.h18
49 files changed, 2067 insertions, 1005 deletions
diff --git a/src/libjin/Common/Exception.cpp b/src/libjin/Common/Exception.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Common/Exception.cpp
diff --git a/src/libjin/Common/Exception.h b/src/libjin/Common/Exception.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Common/Exception.h
diff --git a/src/libjin/Filesystem/Filesystem.cpp b/src/libjin/Filesystem/Filesystem.cpp
index 3f91274..c3d271c 100644
--- a/src/libjin/Filesystem/Filesystem.cpp
+++ b/src/libjin/Filesystem/Filesystem.cpp
@@ -43,6 +43,8 @@ namespace filesystem
return smtread(S, path, len);
}
+
+
const char* Filesystem::getFull(const char* path)
{
return smtfullpath(S, path);
diff --git a/src/libjin/Game/Game.cpp b/src/libjin/Game/Game.cpp
index 6dc75ce..f4e672d 100644
--- a/src/libjin/Game/Game.cpp
+++ b/src/libjin/Game/Game.cpp
@@ -46,6 +46,7 @@ namespace core
if (_onDraw != nullptr)
_onDraw();
wnd->swapBuffers();
+ sleep(1);
}
quitloop:;
}
diff --git a/src/libjin/Graphics/Bitmap.h b/src/libjin/Graphics/Bitmap.h
index 5510569..553d999 100644
--- a/src/libjin/Graphics/Bitmap.h
+++ b/src/libjin/Graphics/Bitmap.h
@@ -6,6 +6,7 @@
#include "../Math/Vector2.hpp"
#include "../3rdparty/GLee/GLee.h"
#include "Color.h"
+
namespace jin
{
namespace graphics
@@ -18,7 +19,7 @@ namespace graphics
static Bitmap* createBitmap(int w, int h, Color color = Color::BLACK);
static Bitmap* clone(const Bitmap* bitmap);
- ~Bitmap();
+ virtual ~Bitmap();
/* init pixels */
void bind(Color* pixels, int w, int h);
void resetPixels(const Color* pixels, int w, int h);
@@ -32,8 +33,9 @@ namespace graphics
/* get width and height */
inline int getWidth() const { return width; }
inline int getHeight() const { return height; }
+ inline math::Vector2<int> getSize() const { return math::Vector2<int>(width, height); }
- private:
+ protected:
Bitmap();
Bitmap(int w, int h);
diff --git a/src/libjin/Graphics/Color.h b/src/libjin/Graphics/Color.h
index 6f9e887..3de49dc 100644
--- a/src/libjin/Graphics/Color.h
+++ b/src/libjin/Graphics/Color.h
@@ -76,12 +76,6 @@ namespace graphics
Channel r, g, b, a;
- //#if LIBJIN_BYTEORDER == LIBJIN_BIG_ENDIAN
- // unsigned char r, g, b, a;
- //#else
- // unsigned char a, b, g, r;
- //#endif
-
};
} // render
diff --git a/src/libjin/Graphics/Drawable.cpp b/src/libjin/Graphics/Drawable.cpp
index 77c3750..4be1cc2 100644
--- a/src/libjin/Graphics/Drawable.cpp
+++ b/src/libjin/Graphics/Drawable.cpp
@@ -10,7 +10,7 @@ namespace jin
{
namespace graphics
{
-
+
Drawable::Drawable(int w, int h)
: texture(0)
, size(w, h)
@@ -27,6 +27,33 @@ namespace graphics
texture_coords[6] = 1; texture_coords[7] = 0;
}
+ Drawable::Drawable(const Bitmap* bitmap)
+ : texture(0)
+ , anchor(0, 0)
+ {
+ unsigned int w = size.w = bitmap->getWidth();
+ unsigned int h = size.h = bitmap->getHeight();
+
+ vertex_coords[0] = 0; vertex_coords[1] = 0;
+ vertex_coords[2] = 0; vertex_coords[3] = h;
+ vertex_coords[4] = w; vertex_coords[5] = h;
+ vertex_coords[6] = w; vertex_coords[7] = 0;
+
+ texture_coords[0] = 0; texture_coords[1] = 0;
+ texture_coords[2] = 0; texture_coords[3] = 1;
+ texture_coords[4] = 1; texture_coords[5] = 1;
+ texture_coords[6] = 1; texture_coords[7] = 0;
+
+ const Color* pixels = bitmap->getPixels();
+
+ texture = gl.genTexture();
+ gl.bindTexture(texture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl.texImage(GL_RGBA8, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ gl.bindTexture(0);
+ }
+
Drawable::~Drawable()
{
glDeleteTextures(1, &texture);
@@ -53,6 +80,38 @@ namespace graphics
gl.bindTexture(0);
}
+ void Drawable::draw(const math::Quad& slice, int x, int y, float sx, float sy, float r, float ax, float ay)
+ {
+ float vertCoords[8] = {
+ 0, 0,
+ 0, slice.h,
+ slice.w, slice.h,
+ slice.w, 0
+ };
+ float slx = slice.x / size.w;
+ float sly = slice.y / size.h;
+ float slw = slice.w / size.w;
+ float slh = slice.h / size.h;
+ float texCoords[8] = {
+ slx, sly,
+ slx, sly + slh,
+ slx + slw, sly + slh,
+ slx + slw, sly
+ };
+
+ gl.ModelMatrix.setTransformation(x, y, r, sx, sy, ax, ay);
+
+ Shader* shader = Shader::getCurrentShader();
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ shader->bindVertexPointer(2, GL_FLOAT, 0, vertCoords);
+ shader->bindUVPointer(2, GL_FLOAT, 0, texCoords);
+
+ gl.bindTexture(texture);
+ gl.drawArrays(GL_QUADS, 0, 4);
+ gl.bindTexture(0);
+ }
+
} // render
} // jin
diff --git a/src/libjin/Graphics/Drawable.h b/src/libjin/Graphics/Drawable.h
index c77068c..0c4c3ef 100644
--- a/src/libjin/Graphics/Drawable.h
+++ b/src/libjin/Graphics/Drawable.h
@@ -3,8 +3,10 @@
#include "../jin_configuration.h"
#if LIBJIN_MODULES_RENDER
+#include "../math/Quad.h"
#include "../math/Vector2.hpp"
#include "OpenGL.h"
+#include "Bitmap.h"
namespace jin
{
@@ -15,10 +17,12 @@ namespace graphics
{
public:
Drawable(int w = 0, int h = 0);
+ Drawable(const Bitmap* bitmap);
virtual ~Drawable();
void setAnchor(int x, int y);
- void draw(int x, int y, float sx, float sy, float r);
+ void draw(int x, int y, float sx = 1, float sy = 1, float r = 0);
+ void draw(const math::Quad& slice, int x, int y, float sx = 1, float sy = 1, float r = 0, float ax = 0, float ay = 0);
inline int getWidth() const { return size.w; }
inline int getHeight() const { return size.h; }
inline GLuint getTexture() const { return texture; }
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
diff --git a/src/libjin/Graphics/Font.h b/src/libjin/Graphics/Font.h
deleted file mode 100644
index 0cb07de..0000000
--- a/src/libjin/Graphics/Font.h
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef __LIBJIN_FONT_H
-#define __LIBJIN_FONT_H
-#include "../jin_configuration.h"
-#if LIBJIN_MODULES_RENDER
-
-#include <vector>
-#include <map>
-#include "drawable.h"
-#include "FontData.h"
-#include "../math/quad.h"
-
-namespace jin
-{
-namespace graphics
-{
-
- struct GlyphVertex
- {
- int x, y; // screen coordinates
- float u, v; // texture uv
- };
-
- struct GlyphArrayDrawInfo
- {
- GLuint texture; // atlas
- unsigned int start; // glyph vertex indecies
- unsigned int count; // glyph vertex count
- };
-
- struct Glyph
- {
- GLuint atlas;
- /* normalized coordinates */
- struct Bbox
- {
- float x, y;
- float width, height;
- } bbox;
- /* glyph size in pixel */
- unsigned int width, height;
- };
-
- struct Page
- {
- std::vector<GlyphArrayDrawInfo> glyphinfolist;
- std::vector<GlyphVertex> glyphvertices;
- int width, height;
- };
-
- class Font
- {
- public:
- typedef unsigned int Codepoint;
-
- static Font* createFont(FontData* fontData, unsigned int fontSzie);
-
- Page* typeset(const char* text, int lineheight, int spacing);
- void print(const char* text, int x, int y, int lineheight, int spacing = 0);
- void print(const Page* page, int x, int y);
- //Bitmap* bake(const char* text);
-#if defined(font_debug)
- void drawAtlas();
-#endif
- ~Font();
-
- private:
- 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];
-
- Font(FontData* font, Codepoint fontSize);
-
- void estimateSize();
- GLuint createAtlas();
- Glyph* bakeGlyph(Codepoint character);
- Glyph* findGlyph(Codepoint character);
-
- int getCharWidth(int c);
- int getCharHeight(int c);
- int getTextWidth(const char* text, int spacing = 0);
- int getTextHeight(const char* text, int lineheight);
- void getTextBox(const char* text, int* w, int* h, int lineheight, int spacing = 0);
-
- int textureWidth;
- int textureHeight;
- std::vector<GLuint> atlases;
- /* map unicode codepoint to glyph */
- std::map<Codepoint, Glyph*> glyphs;
- FontData* font;
- const unsigned int fontsize;
- int baseline;
- int descent;
-
- /* cursor helped render to texture */
- math::Vector2<float> cursor;
-
- };
-
-} // graphics
-} // jin
-
-#endif // LIBJIN_MODULES_RENDER
-#endif // __LIBJIN_FONT_H \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/Decoder.cpp b/src/libjin/Graphics/Font/Decoder.cpp
new file mode 100644
index 0000000..10927f0
--- /dev/null
+++ b/src/libjin/Graphics/Font/Decoder.cpp
@@ -0,0 +1,93 @@
+#include <stdlib.h>
+#include <string.h>
+#include "Decoder.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ /* utf8 byte string to unicode codepoint */
+ static const char *utf8toCodepoint(const char *p, unsigned *res) {
+ return nullptr;
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // decoders
+ /////////////////////////////////////////////////////////////////////////////
+
+ const void* Utf8::decode(const void* data, Codepoint* res) const
+ {
+ const char* p = (char*)data;
+ 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;
+ }
+
+ const void* Utf8::next(const void* data) const
+ {
+ const char* p = (char*)data;
+ 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:
+ return p + 1;
+ }
+ x = (*p & mask) << shift;
+ do {
+ if (*(++p) == '\0') {
+ return p;
+ }
+ shift -= 6;
+ x |= (*p & 0x3f) << shift;
+ } while (shift);
+ return p + 1;
+ }
+/*
+ const void* Utf16::decode(const void* data, Codepoint* res) const
+ {
+ return nullptr;
+ }
+
+ const void* Utf16::next(const void* data) const
+ {
+ return nullptr;
+ }
+*/
+ const void* Ascii::decode(const void* data, Codepoint* res) const
+ {
+ const char* p = (char*)data;
+ *res = *p;
+ return p + 1;
+ }
+
+ const void* Ascii::next(const void* data) const
+ {
+ const char* p = (char*)data;
+ return p + 1;
+ }
+
+} // graphics
+} // jin \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/Decoder.h b/src/libjin/Graphics/Font/Decoder.h
new file mode 100644
index 0000000..4568d65
--- /dev/null
+++ b/src/libjin/Graphics/Font/Decoder.h
@@ -0,0 +1,44 @@
+#ifndef __LIBJIN_UTF8_H
+#define __LIBJIN_UTF8_H
+
+#include <vector>
+
+#include "Text.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ class Decoder
+ {
+ public:
+ virtual const void* decode(const void* data, Codepoint* c) const = 0 ;
+ virtual const void* next(const void* data) const = 0;
+ };
+
+ class Utf8 : public Decoder
+ {
+ public:
+ const void* decode(const void* data, Codepoint* c) const override;
+ const void* next(const void* data) const override;
+ };
+/*
+ class Utf16 : public Decoder
+ {
+ public:
+ const void* decode(const void* data, Codepoint* c) const override;
+ const void* next(const void* data) const override;
+ };
+*/
+ class Ascii : public Decoder
+ {
+ public:
+ const void* decode(const void* data, Codepoint* c) const override;
+ const void* next(const void* data) const override;
+ };
+
+} // graphics
+} // jin
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/Font.h b/src/libjin/Graphics/Font/Font.h
new file mode 100644
index 0000000..424c324
--- /dev/null
+++ b/src/libjin/Graphics/Font/Font.h
@@ -0,0 +1,31 @@
+#ifndef __LIBJIN_FONT_H
+#define __LIBJIN_FONT_H
+#include <vector>
+#include "Text.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ struct Page;
+
+ class Font
+ {
+ public:
+ Font() {}
+ virtual ~Font() {};
+
+ virtual Page* typeset(const Text& text, int lineheight, int spacing = 0) = 0;
+ virtual Page* typeset(const Content& text, int lineheight, int spacing = 0) = 0;
+
+ virtual void print(const Page* page, int x, int y) = 0;
+ virtual void print(const Content& text, int x, int y, int lineheight, int spacing = 0) = 0;
+ virtual void print(const Text& text, int x, int y, int lineheight, int spacing = 0) = 0;
+
+ };
+
+} // graphics
+} // jin
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/Page.h b/src/libjin/Graphics/Font/Page.h
new file mode 100644
index 0000000..6e7cbdf
--- /dev/null
+++ b/src/libjin/Graphics/Font/Page.h
@@ -0,0 +1,38 @@
+#ifndef __LIBJIN_PAGE_H
+#define __LIBJIN_PAGE_H
+#include "../../math/Vector2.hpp"
+#include "Font.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ class Font;
+
+ struct GlyphVertex
+ {
+ int x, y; // screen coordinates
+ float u, v; // texture uv
+ };
+
+ struct GlyphArrayDrawInfo
+ {
+ GLuint texture; // atlas
+ unsigned int start; // glyph vertex indecies
+ unsigned int count; // glyph vertex count
+ };
+
+ /* for reduce draw call */
+ struct Page
+ {
+ Font* font;
+ std::vector<GlyphArrayDrawInfo> glyphinfolist;
+ std::vector<GlyphVertex> glyphvertices;
+ math::Vector2<int> size;
+ };
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/TTF.cpp b/src/libjin/Graphics/Font/TTF.cpp
new file mode 100644
index 0000000..98e57dd
--- /dev/null
+++ b/src/libjin/Graphics/Font/TTF.cpp
@@ -0,0 +1,463 @@
+#include "../../jin_configuration.h"
+#if LIBJIN_MODULES_RENDER
+
+#include <stdio.h>
+
+#include "../../Common/Array.hpp"
+#include "../OpenGL.h"
+#include "../Color.h"
+#include "../Shader.h"
+#include "TTF.h"
+#include "Page.h"
+
+#define STB_TRUETYPE_IMPLEMENTATION
+#include "../../3rdparty/stb/stb_truetype.h"
+
+namespace jin
+{
+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);
+ }
+
+ /*
+ * (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 "../Shaders/font.shader.h"
+
+ using namespace std;
+ using namespace jin::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 };
+
+ /* utf8 byte string to unicode codepoint */
+ static const char* utf8toCodepoint(const char *p, Codepoint *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*/ 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)
+ : cursor(0, 0)
+ , ttf(f)
+ , ttfsize(fontSize)
+ {
+ ttf->pushTTFsize(ttfsize);
+ 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;
+ }
+
+#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)
+
+ 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;
+ for (Codepoint c : text)
+ {
+ if (c == 0x0D)
+ continue;
+ if (c == 0x0A)
+ {
+ /* new line */
+ p.y += lineheight;
+ p.x = 0;
+ 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(ttfsize);
+ 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(ttfsize);
+ 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(ttfsize);
+ 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(ttfsize);
+ *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(ttfsize);
+ GLuint atlas = atlases.back();
+ const Color* bitmap = ttf->getCodepointBitmap(character, &w, &h, &xoff, &yoff);
+ int adw, lsb;
+ {
+ 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);
+ }
+
+} // graphics
+} // jin
+
+#endif // LIBJIN_MODULES_RENDER \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/TTF.h b/src/libjin/Graphics/Font/TTF.h
new file mode 100644
index 0000000..4f51138
--- /dev/null
+++ b/src/libjin/Graphics/Font/TTF.h
@@ -0,0 +1,127 @@
+#ifndef __LIBJINTTF_H
+#define __LIBJIN_TTF_H
+#include "../../jin_configuration.h"
+#if LIBJIN_MODULES_RENDER
+
+#include <vector>
+#include <map>
+
+#include "../../3rdparty/stb/stb_truetype.h"
+#include "../../math/quad.h"
+#include "../Color.h"
+#include "../drawable.h"
+
+#include "Page.h"
+#include "Font.h"
+#include "Text.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ /**
+ * TTFData
+ * |- TTF
+ * |- TTF
+ * .
+ * .
+ * .
+ */
+ class TTFData
+ {
+ public:
+ static TTFData* createTTFData(const unsigned char* data, unsigned int size);
+
+ ~TTFData();
+
+ void pushTTFsize(unsigned int ttfsize);
+ void popTTFsize();
+
+ Channel* getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const;
+ Color* getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const;
+
+ void getVMetrics(int* baseline, int* descent);
+ void getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing);
+
+ private:
+ static const unsigned int FONT_SIZE = 12;
+
+ TTFData(const unsigned char* data, unsigned int size);
+
+ stbtt_fontinfo info;
+ struct
+ {
+ unsigned char* data;
+ unsigned int size;
+ } raw;
+ std::vector<float> scales;
+
+ };
+
+ class TTF : public Font
+ {
+ public:
+ static TTF* createTTF(TTFData* ttfData, unsigned int ttfSzie);
+
+ Page* typeset(const Text& text, int lineheight, int spacing = 0) override;
+ Page* typeset(const Content& text, int lineheight, int spacing = 0) override;
+
+ void print(const Text& text, int x, int y, int lineheight, int spacing = 0) override;
+ void print(const Content& text, int x, int y, int lineheight, int spacing = 0) override;
+ void print(const Page* page, int x, int y) override;
+
+ ~TTF();
+
+ private:
+ struct TTFGlyph
+ {
+ GLuint atlas;
+ /* normalized coordinates */
+ struct Bbox
+ {
+ float x, y;
+ float w, h;
+ } bbox;
+ /* glyph size in pixel */
+ unsigned int width, height;
+ };
+
+ 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];
+
+ TTF(TTFData* ttf, Codepoint ttfSize);
+
+ void estimateSize();
+ GLuint createAtlas();
+ TTFGlyph& bakeGlyph(Codepoint character);
+ TTFGlyph& findGlyph(Codepoint character);
+
+ int getCharWidth(int c);
+ int getCharHeight(int c);
+
+ int getTextWidth(const Content& text, int spacing = 0);
+ int getTextHeight(const Content& text, int lineheight);
+ void getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing = 0);
+
+ int textureWidth;
+ int textureHeight;
+ std::vector<GLuint> atlases;
+ std::map<Codepoint, TTFGlyph> glyphs;
+ TTFData* ttf;
+ const unsigned int ttfsize;
+ int baseline;
+ int descent;
+
+ /* cursor helped render to texture */
+ math::Vector2<float> cursor;
+
+ };
+
+} // graphics
+} // jin
+
+#endif // LIBJIN_MODULES_RENDER
+#endif // __LIBJIN_FONT_H \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/Text.cpp b/src/libjin/Graphics/Font/Text.cpp
new file mode 100644
index 0000000..68601de
--- /dev/null
+++ b/src/libjin/Graphics/Font/Text.cpp
@@ -0,0 +1,151 @@
+#include <cstring>
+
+#include "Text.h"
+#include "Decoder.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ /////////////////////////////////////////////////////////////////////////////
+ // iterator
+ /////////////////////////////////////////////////////////////////////////////
+
+ Text::Iterator::Iterator(const Iterator& itor)
+ : data(itor.data)
+ , p(itor.p)
+ , encode(itor.encode)
+ , length(itor.length)
+ {
+ switch (encode)
+ {
+ case Encode::UTF8: decoder = new Utf8(); break;
+ //case Encode::UTF16: decoder = new Utf16(); break;
+ case Encode::ASCII: decoder = new Ascii(); break;
+ }
+ }
+
+ Text::Iterator::Iterator(const Encode& _encode, const void* _data, unsigned int _length)
+ : data(_data)
+ , p(_data)
+ , encode(_encode)
+ , length(_length)
+ {
+ switch (encode)
+ {
+ case Encode::UTF8: decoder = new Utf8(); break;
+ //case Encode::UTF16: decoder = new Utf16(); break;
+ case Encode::ASCII: decoder = new Ascii(); break;
+ }
+ }
+
+ Text::Iterator::~Iterator()
+ {
+ delete decoder;
+ }
+
+ Codepoint Text::Iterator::get()
+ {
+ Codepoint codepoint;
+ decoder->decode(p, &codepoint);
+ return codepoint;
+ }
+
+ Codepoint Text::Iterator::operator*()
+ {
+ return get();
+ }
+
+ Text::Iterator Text::Iterator::begin()
+ {
+ Iterator itor(encode, data, length);
+ itor.toBegin();
+ return itor;
+ }
+
+ Text::Iterator Text::Iterator::end()
+ {
+ Iterator itor(encode, data, length);
+ itor.toEnd();
+ return itor;
+ }
+
+ void Text::Iterator::toBegin()
+ {
+ p = (const unsigned char*)data;
+ }
+
+ void Text::Iterator::toEnd()
+ {
+ p = (const unsigned char*)data + length;
+ }
+
+ Text::Iterator& Text::Iterator::operator ++()
+ {
+ p = decoder->next(p);
+ return *this;
+ }
+
+ Text::Iterator Text::Iterator::operator ++(int)
+ {
+ p = decoder->next(p);
+ Iterator itor(encode, data, length);
+ itor.p = p;
+ return itor;
+ }
+
+ bool Text::Iterator::operator !=(const Iterator& itor)
+ {
+ return !(data == itor.data
+ && p == itor.p
+ && length == itor.length
+ && encode == itor.encode);
+ }
+
+ bool Text::Iterator::operator ==(const Iterator& itor)
+ {
+ return data == itor.data
+ && p == itor.p
+ && length == itor.length
+ && encode == itor.encode;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // text
+ /////////////////////////////////////////////////////////////////////////////
+
+ Text::Text(Encode encode, const void* data)
+ {
+ Iterator it = Iterator(encode, data, strlen((const char*)data));
+ for (; it != it.end(); ++it)
+ {
+ content.push_back(*it);
+ }
+ }
+
+ Text::Text(Encode _encode, const void* _data, unsigned int _length)
+ {
+ Iterator it = Iterator(_encode, _data, _length);
+ for (; it != it.end(); ++it)
+ {
+ content.push_back(*it);
+ }
+ }
+
+ Text::~Text()
+ {
+ }
+
+ const Content& Text::getContent() const
+ {
+ return content;
+ }
+
+ const Content& Text::operator*() const
+ {
+ return content;
+ }
+
+} // graphics
+} // jin \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/Text.h b/src/libjin/Graphics/Font/Text.h
new file mode 100644
index 0000000..3faabc0
--- /dev/null
+++ b/src/libjin/Graphics/Font/Text.h
@@ -0,0 +1,74 @@
+#ifndef __LIBJIN_TEXT_H
+#define __LIBJIN_TEXT_H
+
+#include <vector>
+
+namespace jin
+{
+namespace graphics
+{
+
+ typedef unsigned int Codepoint;
+
+ typedef std::vector<Codepoint> Content;
+
+ class Text;
+ class Decoder;
+
+ enum Encode
+ {
+ UTF8, // utf-8
+ //UTF16, // utf-16
+ ASCII, // ASCII
+ };
+
+ /* raw encoded text */
+ class Text
+ {
+ public:
+ Text(Encode encode, const void* data);
+ Text(Encode encode, const void* data, unsigned int length);
+ ~Text();
+
+ const Content& getContent() const;
+ const Content& operator*() const;
+
+ private:
+ class Iterator
+ {
+ public:
+ Iterator(const Iterator& itor);
+ Iterator(const Encode& encode, const void* data, unsigned int length);
+ ~Iterator();
+
+ Codepoint get();
+ Iterator begin();
+ Iterator end();
+ void toBegin();
+ void toEnd();
+ Codepoint operator *();
+ /* prefix ++ */
+ Iterator& operator ++();
+ /* postfix ++ */
+ Iterator operator ++(int);
+ bool operator !=(const Iterator& itor);
+ bool operator ==(const Iterator& itor);
+
+ private:
+ void operator = (const Iterator&);
+
+ const Encode encode;
+ const Decoder* decoder;
+ const void* p;
+ const void* const data;
+ unsigned int length;
+ };
+
+ Content content;
+
+ };
+
+} // graphics
+} // jin
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/TextureFont.cpp b/src/libjin/Graphics/Font/TextureFont.cpp
new file mode 100644
index 0000000..4dde236
--- /dev/null
+++ b/src/libjin/Graphics/Font/TextureFont.cpp
@@ -0,0 +1,300 @@
+#include <vector>
+
+#include "../../Math/Vector2.hpp"
+#include "../Shader.h"
+#include "TextureFont.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ using namespace std;
+ using namespace math;
+
+ TextureFont * TextureFont::createTextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh)
+ {
+ TextureFont* tf = new TextureFont(bitmap, codepoints, cellw, cellh);
+ return tf;
+ }
+
+ TextureFont * TextureFont::createTextureFont(const Bitmap* bitmap, const Text& codepoints, int cellw, int cellh)
+ {
+ TextureFont* tf = new TextureFont(bitmap, *codepoints, cellw, cellh);
+ return tf;
+ }
+
+ TextureFont* TextureFont::createTextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh)
+ {
+ TextureFont* tf = new TextureFont(bitmap, codepoints, mask, cellh);
+ return tf;
+ }
+
+ TextureFont* TextureFont::createTextureFont(const Bitmap* bitmap, const Text& codepoints, Color mask, int cellh)
+ {
+ TextureFont* tf = new TextureFont(bitmap, *codepoints, mask, cellh);
+ return tf;
+ }
+
+ TextureFont::~TextureFont()
+ {
+ }
+
+ const TextureFont::TextureGlyph* TextureFont::findGlyph(Codepoint codepoint) const
+ {
+ auto it = glyphs.find(codepoint);
+ if (it != glyphs.end())
+ {
+ return &it->second;
+ }
+ else
+ return nullptr;
+ }
+
+ Page* TextureFont::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;
+ const TextureGlyph* 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);\
+
+ for (Codepoint c : text)
+ {
+ if (c == 0x0D)
+ continue;
+ if (c == 0x0A)
+ {
+ /* new line */
+ p.y += lineheight;
+ p.x = 0;
+ continue;
+ }
+ glyph = findGlyph(c);
+ if (glyph == nullptr)
+ continue;
+ if (texture != this->texture)
+ {
+ texture = this->texture;
+ GlyphArrayDrawInfo info;
+ info.start = i;
+ info.count = 0;
+ info.texture = texture;
+ glyphinfolist.push_back(info);
+ }
+ glyphinfolist[glyphinfolist.size() - 1].count += 4;
+ // normalized
+ float nx = glyph->x / (float)size.w, ny = glyph->y / (float)size.h;
+ float nw = glyph->w / (float)size.w, nh = glyph->h / (float)size.h;
+ glyphvertices_push(p.x, p.y, nx, ny);
+ glyphvertices_push(p.x, p.y + glyph->h, nx, ny + nh);
+ glyphvertices_push(p.x + glyph->w, p.y + glyph->h, nx + nw, ny + nh);
+ glyphvertices_push(p.x + glyph->w, p.y, nx + nw, ny);
+ p.x += glyph->w + spacing;
+ i += 4;
+ }
+ getTextBox(text, &page->size.w, &page->size.h, lineheight, spacing);
+ return page;
+ }
+
+ int TextureFont::getCharWidth(int c)
+ {
+ auto it = glyphs.find(c);
+ if (it != glyphs.end())
+ {
+ return it->second.w;
+ }
+ return 0;
+ }
+
+ int TextureFont::getCharHeight(int c)
+ {
+ auto it = glyphs.find(c);
+ if (it != glyphs.end())
+ {
+ return it->second.h;
+ }
+ return 0;
+ }
+
+ int TextureFont::getTextWidth(const Content& t, int spacing)
+ {
+ 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;
+ }
+ return res;
+ }
+
+ int TextureFont::getTextHeight(const Content& t, int lineheight)
+ {
+ 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;
+ }
+ }
+ return res;
+ }
+
+ void TextureFont::getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing)
+ {
+ *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;
+ }
+ }
+
+ Page* TextureFont::typeset(const Text& text, int lineheight, int spacing)
+ {
+ return typeset(*text, lineheight, spacing);
+ }
+
+ void TextureFont::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 TextureFont::print(const Content& text, int x, int y, int lineheight, int spacing)
+ {
+ Page* page = typeset(text, lineheight, spacing);
+ print(page, x, y);
+ delete page;
+ }
+
+ void TextureFont::print(const Text& text, int x, int y, int lineheight, int spacing)
+ {
+ Page* page = typeset(text, lineheight, spacing);
+ print(page, x, y);
+ delete page;
+ }
+
+ TextureFont::TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh)
+ : Drawable(bitmap)
+ {
+ TextureGlyph glyph;
+ Vector2<int> count(bitmap->getWidth() / cellw, bitmap->getHeight() / cellh);
+ glyph.w = cellw;
+ glyph.h = cellh;
+ for (int y = 0; y < count.row; ++y)
+ {
+ glyph.y = y * cellh;
+ for (int x = 0; x < count.colum; ++x)
+ {
+ glyph.x = x * cellw;
+ if (x + y * count.colum >= codepoints.size())
+ return;
+ glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[x + y * count.colum], glyph));
+ }
+ }
+ }
+
+ TextureFont::TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh)
+ : Drawable(bitmap)
+ {
+ TextureGlyph glyph;
+ glyph.h = cellh;
+ int w = bitmap->getWidth();
+ int h = bitmap->getHeight();
+ int i = 0;
+ for (int y = 0; y < h; y += cellh)
+ {
+ glyph.y = y;
+ bool newc = false;
+ for (int x = 0; x <= w; ++x)
+ {
+ if (x == w && newc)
+ {
+ glyph.w = x - glyph.x;
+ if (i >= codepoints.size())
+ return;
+ glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[i], glyph));
+ ++i;
+ newc = false;
+ break;
+ }
+ Color c = bitmap->getPixels()[x + y * w];
+ if (!newc && c != mask)
+ {
+ glyph.x = x;
+ newc = true;
+ }
+ else if (newc && c == mask)
+ {
+ glyph.w = x - glyph.x;
+ if (i >= codepoints.size())
+ return;
+ glyphs.insert(std::pair<Codepoint, TextureGlyph>(codepoints[i], glyph));
+ if (codepoints[i] == 't')
+ {
+ int a = 10;
+ }
+ ++i;
+ newc = false;
+ }
+ }
+ }
+ }
+
+}
+} \ No newline at end of file
diff --git a/src/libjin/Graphics/Font/TextureFont.h b/src/libjin/Graphics/Font/TextureFont.h
new file mode 100644
index 0000000..0d0d091
--- /dev/null
+++ b/src/libjin/Graphics/Font/TextureFont.h
@@ -0,0 +1,62 @@
+#ifndef __LIBJIN_TEXTURE_FONT_H
+#define __LIBJIN_TEXTURE_FONT_H
+
+#include <map>
+#include <vector>
+
+#include "../../Math/Vector4.hpp"
+#include "../Drawable.h"
+#include "../Bitmap.h"
+
+#include "Page.h"
+#include "Font.h"
+#include "Text.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ /* Texture font */
+ class TextureFont : public Font
+ , public Drawable
+ {
+ public:
+ static TextureFont* createTextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh);
+ static TextureFont* createTextureFont(const Bitmap* bitmap, const Text& text, int cellw, int cellh);
+ static TextureFont* createTextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh);
+ static TextureFont* createTextureFont(const Bitmap* bitmap, const Text& text, Color mask, int cellh);
+
+ ~TextureFont();
+
+ Page* typeset(const Text& text, int lineheight, int spacing = 0) override;
+ Page* typeset(const Content& text, int lineheight, int spacing = 0) override ;
+
+ void print(const Page* page, int x, int y) override;
+ void print(const Content& text, int x, int y, int linehgiht, int spacing = 0) override;
+ void print(const Text& text, int x, int y, int lineheight, int spacing = 0)override;
+
+ private:
+ struct TextureGlyph
+ {
+ float x, y, w, h;
+ };
+
+ TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh);
+ TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh);
+
+ int getCharWidth(int c);
+ int getCharHeight(int c);
+ int getTextWidth(const Content& text, int spacing = 0);
+ int getTextHeight(const Content& text, int lineheight);
+ void getTextBox(const Content& text, int* w, int* h, int lineheight, int spacing = 0);
+ const TextureGlyph* findGlyph(Codepoint codepoint) const;
+
+ std::map<Codepoint, TextureGlyph> glyphs;
+
+ };
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/FontData.cpp b/src/libjin/Graphics/FontData.cpp
deleted file mode 100644
index 1b66b12..0000000
--- a/src/libjin/Graphics/FontData.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-#include "FontData.h"
-#define STB_TRUETYPE_IMPLEMENTATION
-#include "../3rdparty/stb/stb_truetype.h"
-#include <stdio.h>
-
-namespace jin
-{
-namespace graphics
-{
-
- FontData* FontData::createFontData(const unsigned char* data, unsigned int size)
- {
- FontData* font = nullptr;
- try
- {
- font = new FontData(data, size);
- return font;
- }
- catch (...)
- {
- return nullptr;
- }
- }
-
- FontData::FontData(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 */
- pushFontsize(FONT_SIZE);
- }
-
- FontData::~FontData()
- {
- free(raw.data);
- }
-
- /*
- * (0, 0)
- * +--------------+ ascent
- * | +--------+ |
- * | | | |
- * | | bitmap | |
- * +--|--------|--+ baseline
- * | +--------+ |
- * +--|-----------+ decent
- * | |
- * leftSideBearing |
- * |
- * advanceWidth
- */
- void FontData::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 FontData::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 FontData::pushFontsize(unsigned int fs)
- {
- float sc = stbtt_ScaleForPixelHeight(&info, fs);
- scales.push_back(sc);
- }
-
- void FontData::popFontsize()
- {
- /* always keep default font size on the bottom of stack */
- if(scales.size() > 1)
- scales.pop_back();
- }
-
- Channel* FontData::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* FontData::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;
- }
-
-}
-} \ No newline at end of file
diff --git a/src/libjin/Graphics/FontData.h b/src/libjin/Graphics/FontData.h
deleted file mode 100644
index c75b9a1..0000000
--- a/src/libjin/Graphics/FontData.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef __LIBJIN_FONTDATA_H
-#define __LIBJIN_FONTDATA_H
-#include "../3rdparty/stb/stb_truetype.h"
-#include "Color.h"
-#include <vector>
-
-namespace jin
-{
-namespace graphics
-{
-
- class FontData
- {
- public:
- static FontData* createFontData(const unsigned char* data, unsigned int size);
-
- ~FontData();
-
- void pushFontsize(unsigned int fontsize);
- void popFontsize();
-
- Channel* getCodepointBitmapAlpha(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const;
- Color* getCodepointBitmap(unsigned int codepoint, int* width, int* height, int* xoff, int* yoff) const;
- void getVMetrics(int* baseline, int* descent);
- void getHMetrics(unsigned int codepoint, int* advanceWidth, int* leftSideBearing);
-
- private:
- static const unsigned int FONT_SIZE = 12;
-
- FontData(const unsigned char* data, unsigned int size);
-
- stbtt_fontinfo info;
- struct
- {
- unsigned char* data;
- unsigned int size;
- } raw;
- std::vector<float> scales;
-
- };
-
-}
-}
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Graphics.h b/src/libjin/Graphics/Graphics.h
index a4bf98b..54889f9 100644
--- a/src/libjin/Graphics/Graphics.h
+++ b/src/libjin/Graphics/Graphics.h
@@ -5,13 +5,15 @@
#include "canvas.h"
#include "color.h"
-#include "FontData.h"
-#include "Font.h"
#include "Shapes.h"
#include "texture.h"
#include "Shader.h"
#include "window.h"
#include "Bitmap.h"
+#include "./Font/TTF.h"
+#include "./Font/Text.h"
+#include "./Font/TextureFont.h"
+
#endif // LIBJIN_MODULES_RENDER
#endif // __LIBJIN_GRAPHICS_H \ No newline at end of file
diff --git a/src/libjin/Graphics/Image.cpp b/src/libjin/Graphics/Image.cpp
new file mode 100644
index 0000000..6203395
--- /dev/null
+++ b/src/libjin/Graphics/Image.cpp
@@ -0,0 +1,34 @@
+#include "../3rdparty/stb/stb_image.h"
+#include "Image.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ /*static*/ Image* Image::createImage(const void* imgData, size_t size)
+ {
+ if (imgData == nullptr)
+ return nullptr;
+ int w, h;
+ void* data = stbi_load_from_memory((unsigned char *)imgData, size, &w, &h, NULL, STBI_rgb_alpha);
+ if (data == nullptr)
+ return nullptr;
+ Image* image = new Image();
+ image->pixels = (Color*)data;
+ image->width = w;
+ image->height = h;
+ return image;
+ }
+
+ Image::Image()
+ : Bitmap()
+ {
+ }
+
+ Image::~Image()
+ {
+ }
+
+}
+}
diff --git a/src/libjin/Graphics/Image.h b/src/libjin/Graphics/Image.h
new file mode 100644
index 0000000..5c426dc
--- /dev/null
+++ b/src/libjin/Graphics/Image.h
@@ -0,0 +1,33 @@
+#ifndef __LIBJIN_IMAGE_H
+#define __LIBJIN_IMAGE_H
+
+#include "Bitmap.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ /* just like bitmap but only from image file*/
+ class Image : public Bitmap
+ {
+ public:
+ static Image* createImage(const void* imgData, size_t size);
+ ~Image();
+
+ private:
+ Image();
+
+ void bind(Color* pixels, int w, int h);
+ void resetPixels(const Color* pixels, int w, int h);
+ void resetPixels(const Color& pixels, int w, int h);
+ void setPixel(const Color& pixel, int x, int y);
+ void setPixels(Color pixels);
+ void setPixels(Color* pixels);
+
+ };
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Particles/Particle.cpp b/src/libjin/Graphics/Particles/Particle.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Graphics/Particles/Particle.cpp
diff --git a/src/libjin/Graphics/Particles/Particle.h b/src/libjin/Graphics/Particles/Particle.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Graphics/Particles/Particle.h
diff --git a/src/libjin/Graphics/Shaders/base.shader.h b/src/libjin/Graphics/Shaders/base.shader.h
index bf41c4f..45b63cd 100644
--- a/src/libjin/Graphics/Shaders/base.shader.h
+++ b/src/libjin/Graphics/Shaders/base.shader.h
@@ -1,31 +1,5 @@
-#ifndef LIBJIN_BASE_SHADER_H
-#define LIBJIN_BASE_SHADER_H
-/*
- * https://stackoverflow.com/questions/10868958/what-does-sampler2d-store
- * The sampler2D is bound to a texture unit. The glUniform call binds it to texture
- * unit zero. The glActiveTexture call is only needed if you are going to use multiple
- * texture units (because GL_TEXTURE0 is the default anyway).
-*/
-/*
-#VERTEX_SHADER
-
-vertex vert(vertex v)
-{
- return v;
-}
-
-#END_VERTEX_SHADER
-
-#FRAGMENT_SHADER
-
-vec4 frag(vec4 color, Texture tex, vertex v)
-{
- return Texel(tex, v.uv);
-}
-
-#END_FRAGMENT_SHADER
-
-*/
+#ifndef __LIBJIN_BASE_SHADER_H
+#define __LIBJIN_BASE_SHADER_H
static const char* base_shared = R"(
#define Number float
diff --git a/src/libjin/Graphics/Sprite.cpp b/src/libjin/Graphics/Sprite.cpp
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/libjin/Graphics/Sprite.cpp
diff --git a/src/libjin/Graphics/Sprite.h b/src/libjin/Graphics/Sprite.h
new file mode 100644
index 0000000..acb8264
--- /dev/null
+++ b/src/libjin/Graphics/Sprite.h
@@ -0,0 +1,18 @@
+#ifndef __LIBJIN_IMAGE_H
+#define __LIBJIN_IMAGE_H
+
+namespace jin
+{
+namespace graphics
+{
+
+ /* just like texture but with x,y */
+ class Sprite
+ {
+
+ };
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/src/libjin/Graphics/Texture.cpp b/src/libjin/Graphics/Texture.cpp
index 5a39f77..a42e796 100644
--- a/src/libjin/Graphics/Texture.cpp
+++ b/src/libjin/Graphics/Texture.cpp
@@ -20,18 +20,8 @@ namespace graphics
}
Texture::Texture(const Bitmap* bitmap)
- : Drawable(bitmap->getWidth(), bitmap->getHeight())
+ : Drawable(bitmap)
{
- unsigned int w = size.w;
- unsigned int h = size.h;
- const Color* pixels = bitmap->getPixels();
-
- texture = gl.genTexture();
- gl.bindTexture(texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- gl.texImage(GL_RGBA8, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
- gl.bindTexture(0);
}
Texture::~Texture()
diff --git a/src/libjin/Graphics/Utf8.cpp b/src/libjin/Graphics/Utf8.cpp
deleted file mode 100644
index 1a79d43..0000000
--- a/src/libjin/Graphics/Utf8.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#include <stdlib.h>
-#include <string.h>
-#include "Utf8.h"
-
-namespace jin
-{
-namespace graphics
-{
-
- /* 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;
- }
-
- Utf8::Utf8(const char* raw, unsigned int length)
- {
- _length = length;
- _raw = (char*)calloc(1, length);
- memcpy(_raw, raw, length);
- }
-
- Utf8::Iterator Utf8::getIterator()
- {
- return Iterator(*this);
- }
-
- Utf8::~Utf8()
- {
- free(_raw);
- _raw = nullptr;
- _length = 0;
- }
-
- Utf8::Iterator::Iterator(const Utf8& utf8)
- : _utf8(utf8)
- {
- _p = utf8._raw;
- }
-
- Codepoint Utf8::Iterator::get()
- {
- Codepoint c;
- _p = utf8toCodepoint(_p, &c);
- return c;
- }
-
-}
-} \ No newline at end of file
diff --git a/src/libjin/Graphics/Utf8.h b/src/libjin/Graphics/Utf8.h
deleted file mode 100644
index d2d11fb..0000000
--- a/src/libjin/Graphics/Utf8.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#ifndef __LIBJIN_UTF8_H
-#define __LIBJIN_UTF8_H
-
-namespace jin
-{
-namespace graphics
-{
-
- typedef unsigned int Codepoint;
-
- class Utf8
- {
- public:
- class Iterator
- {
- public:
- /* unicode codepoint */
- Codepoint get();
-
- private:
- friend class Utf8;
- Iterator(const Utf8&);
-
- const char* _p;
- const Utf8& _utf8;
- };
-
- /* rawıսij */
- Utf8(const char* raw, unsigned int length);
- Iterator getIterator();
-
- private:
- friend class Utf8::Iterator;
- ~Utf8();
-
- char* _raw;
- unsigned int _length;
-
- };
-
-}
-}
-
-#endif \ No newline at end of file
diff --git a/src/libjin/Math/Vector2.hpp b/src/libjin/Math/Vector2.hpp
index bee22f3..ddb8221 100644
--- a/src/libjin/Math/Vector2.hpp
+++ b/src/libjin/Math/Vector2.hpp
@@ -26,8 +26,9 @@ namespace math
}
T &x = data[0], &y = data[1]; // xy
- T &w = data[0], &h = data[1]; // wh
-
+ T &w = data[0], &h = data[1]; // wh
+ T &colum = data[0], &row = data[1]; // colum row
+
private:
T data[2];
diff --git a/src/libjin/Math/Vector4.hpp b/src/libjin/Math/Vector4.hpp
index c7dfaa8..da4110f 100644
--- a/src/libjin/Math/Vector4.hpp
+++ b/src/libjin/Math/Vector4.hpp
@@ -32,6 +32,7 @@ namespace math
T &x = data[0], &y = data[1], &z = data[2], &t = data[3]; // xyzt
T &w = data[2], &h = data[3]; // xywh
T &r = data[0], &g = data[1], &b = data[2], &a = data[3]; // rgb
+ T &left = data[0], &right = data[1], &top = data[2], &bottom = data[3]; // lrtb
private:
T data[4];
diff --git a/src/lua/common/Proxy.h b/src/lua/common/Proxy.h
index 101fe9c..643dd48 100644
--- a/src/lua/common/Proxy.h
+++ b/src/lua/common/Proxy.h
@@ -27,6 +27,18 @@ namespace lua
}
}
+ void retain()
+ {
+ if (reference != nullptr)
+ reference->retain();
+ }
+
+ void setUserdata(void* data)
+ {
+ if (reference != nullptr)
+ reference->setUserdata(data);
+ }
+
template<class T>
Ref<T>& getRef()
{
diff --git a/src/lua/common/Reference.hpp b/src/lua/common/Reference.hpp
index feb96bb..bd9dc24 100644
--- a/src/lua/common/Reference.hpp
+++ b/src/lua/common/Reference.hpp
@@ -23,6 +23,16 @@ namespace lua
// object type string
const char* const type;
+ void setUserdata(void* data)
+ {
+ userdata = data;
+ }
+
+ void* getUserdata()
+ {
+ return userdata;
+ }
+
protected:
RefBase(void* obj, const char* t)
: count(1)
@@ -39,7 +49,7 @@ namespace lua
void* object;
int count;
-
+ void* userdata;
};
template<class T>
diff --git a/src/lua/embed/graphics.lua.h b/src/lua/embed/graphics.lua.h
index 1bad4f5..288d2f4 100644
--- a/src/lua/embed/graphics.lua.h
+++ b/src/lua/embed/graphics.lua.h
@@ -17,11 +17,12 @@ Vertex vert(Vertex v)
Color frag(Color col, Texture tex, Vertex v)
{
- return col;
+ return col * texel(tex, v.uv);
}
#END_FRAGMENT_SHADER
]]
+
local _init = jin.graphics.init
jin.graphics.init = function(setting)
diff --git a/src/lua/libraries/luax/luax.h b/src/lua/libraries/luax/luax.h
index 0b3a713..fd10737 100644
--- a/src/lua/libraries/luax/luax.h
+++ b/src/lua/libraries/luax/luax.h
@@ -87,6 +87,7 @@ inline bool luax_checkbool(lua_State *L, int numArg)
/**
* Oprating tables.
*/
+/* get value and leaves it on top of stack */
#define luax_rawgetnumber(L, i, k) (lua_rawgeti(L,i, k), lua_tonumber(L, -1))
/**
diff --git a/src/lua/modules/graphics/bitmap.cpp b/src/lua/modules/graphics/bitmap.cpp
index 6067442..f2ecb5f 100644
--- a/src/lua/modules/graphics/bitmap.cpp
+++ b/src/lua/modules/graphics/bitmap.cpp
@@ -109,5 +109,5 @@ namespace lua
return 0;
}
-}
-} \ No newline at end of file
+} // graphics
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/font.cpp b/src/lua/modules/graphics/font.cpp
deleted file mode 100644
index 0b0e1a0..0000000
--- a/src/lua/modules/graphics/font.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "lua/modules/luax.h"
-#include "lua/modules/types.h"
-#include "lua/common/common.h"
-#include "libjin/jin.h"
-
-namespace jin
-{
-namespace lua
-{
-
- using namespace jin::graphics;
-
- typedef Ref<Font>& FontRef;
-
- static int l_gc(lua_State* L)
- {
- Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_FONT);
- proxy->release();
- return 0;
- }
-
- static int l_typeset(lua_State* L)
- {
- Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_FONT);
- const char* text = luax_checkstring(L, 2);
- int lineheight = luax_checkinteger(L, 3);
- int spacing = luax_checkinteger(L, 4);
- Ref<Font>& refFont = p->getRef<Font>();
- Font* font = refFont.getObject();
- Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_PAGE, sizeof(Proxy));
- Page* page = font->typeset(text, lineheight, spacing);
- proxy->bind(new Ref<Page>(page, JIN_GRAPHICS_PAGE));
- return 1;
- }
-
- static int l_print(lua_State* L)
- {
- Proxy* pFont = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_FONT);
- Font* font = pFont->getObject<Font>();
- if (luax_istype(L, 2, JIN_GRAPHICS_PAGE))
- {
- Proxy* p = (Proxy*)luax_checktype(L, 2, JIN_GRAPHICS_PAGE);
- Page* page = p->getObject<Page>();
- int x = luax_checkinteger(L, 3);
- int y = luax_checkinteger(L, 4);
- font->print(page, x, y);
- }
- else if (luax_isstring(L, 2))
- {
- const char* text = luax_checkstring(L, 2);
- int x = luax_checkinteger(L, 3);
- int y = luax_checkinteger(L, 4);
- int lh = luax_checkinteger(L, 5);
- int sp = luax_checkinteger(L, 6);
- font->print(text, x, y, lh, sp);
- }
- else
- {
- luax_typerror(L, 2, "font or string");
- }
- return 0;
- }
-
- static const luaL_Reg f[] = {
- { "__gc", l_gc },
- { "typeset", l_typeset },
- { "print", l_print },
- { 0, 0 }
- };
-
- int luaopen_Font(lua_State* L)
- {
- luax_newtype(L, JIN_GRAPHICS_FONT, f);
-
- return 0;
- }
-
-} // lua
-} // jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/fontData.cpp b/src/lua/modules/graphics/fontData.cpp
deleted file mode 100644
index 85704d7..0000000
--- a/src/lua/modules/graphics/fontData.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "lua/modules/luax.h"
-#include "lua/modules/types.h"
-#include "lua/common/common.h"
-#include "libjin/jin.h"
-
-namespace jin
-{
-namespace lua
-{
-
- using namespace jin::graphics;
-
- static int l_newFont(lua_State* L)
- {
- Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_FONTDATA);
- int fontsize = luax_checkinteger(L, 2);
- Ref<FontData>& refFontData = p->getRef<FontData>();
- FontData* fontData = refFontData.getObject();
- Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_FONT, sizeof(Proxy));
- Font* font = Font::createFont(fontData, fontsize);
- proxy->bind(new Ref<Font>(font, JIN_GRAPHICS_FONT));
- return 1;
- }
-
- static int l_gc(lua_State* L)
- {
- Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_FONTDATA);
- p->release();
- return 0;
- }
-
- static const luaL_Reg f[] = {
- { "__gc", l_gc },
- { "newFont", l_newFont },
- { 0, 0 }
- };
-
- int luaopen_FontData(lua_State* L)
- {
- luax_newtype(L, JIN_GRAPHICS_FONTDATA, f);
- return 0;
- }
-
-} // lua
-} // jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/graphics.cpp b/src/lua/modules/graphics/graphics.cpp
index 5c67421..a62802c 100644
--- a/src/lua/modules/graphics/graphics.cpp
+++ b/src/lua/modules/graphics/graphics.cpp
@@ -169,18 +169,6 @@ namespace lua
static int l_clear(lua_State* L)
{
- if (luax_gettop(L) == 0)
- {
- glClearColor(0, 0, 0, 1);
- }
- else
- {
- int r = luax_checknumber(L, 1);
- int g = luax_checknumber(L, 2);
- int b = luax_checknumber(L, 3);
- int a = luax_checknumber(L, 4);
- glClearColor(r / 255.f, g / 255.f, b / 255.f, a / 255.f);
- }
glClear(GL_COLOR_BUFFER_BIT);
return 0;
}
@@ -189,7 +177,7 @@ namespace lua
{
if (luax_gettop(L) == 0)
{
- glClearColor(1, 1, 1, 1);
+ glClearColor(0, 0, 0, 1);
return 0;
}
@@ -198,10 +186,10 @@ namespace lua
context.curClearColor.b = luax_checknumber(L, 3);
context.curClearColor.a = luax_checknumber(L, 4);
- glClearColor(context.curClearColor.r / 255.f,
- context.curClearColor.g / 255.f,
- context.curClearColor.b / 255.f,
- context.curClearColor.a / 255.f);
+ gl.setClearColor(context.curClearColor.r,
+ context.curClearColor.g,
+ context.curClearColor.b,
+ context.curClearColor.a);
return 0;
}
@@ -211,30 +199,153 @@ namespace lua
return 0;
}
+ static void l_draw_texture(lua_State* L)
+ {
+ if (!luax_istype(L, 1, JIN_GRAPHICS_TEXTURE))
+ return;
+ int x = luax_optnumber(L, 2, 0);
+ int y = luax_optnumber(L, 3, 0);
+ float sx = luax_optnumber(L, 4, 1);
+ float sy = luax_optnumber(L, 5, 1);
+ float r = luax_optnumber(L, 6, 0);
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Ref<Texture>& tex = proxy->getRef<Texture>();
+ tex->draw(x, y, sx, sy, r);
+ }
+
+ static void l_draw_canvas(lua_State* L)
+ {
+ if (!luax_istype(L, 1, JIN_GRAPHICS_CANVAS))
+ return;
+ int x = luax_optnumber(L, 2, 0);
+ int y = luax_optnumber(L, 3, 0);
+ float sx = luax_optnumber(L, 4, 1);
+ float sy = luax_optnumber(L, 5, 1);
+ float r = luax_optnumber(L, 6, 0);
+ Proxy* proxy = (Proxy*)luax_toudata(L, 1);
+ Ref<Canvas>& p = proxy->getRef<Canvas>();
+ p->draw(x, y, sx, sy, r);
+ }
+
+ /* jin.graphics.draw(text, font, x, y) */
+ static void l_draw_text(lua_State* L)
+ {
+ if (!luax_istype(L, 1, JIN_GRAPHICS_TEXT))
+ return;
+ Proxy* p = (Proxy*)luax_toudata(L, 1);
+ Text* text = p->getObject<Text>();
+ Proxy* p2 = (Proxy*)luax_toudata(L, 2);
+ int x = luax_optnumber(L, 3, 0);
+ int y = luax_optnumber(L, 4, 0);
+ int lineheight = luax_optnumber(L, 5, 12);
+ int spacing = luax_optnumber(L, 6, 0);
+ if (luax_istype(L, 2, JIN_GRAPHICS_TEXTUREFONT))
+ {
+ TextureFont* tf = p2->getObject<TextureFont>();
+ tf->print(*text, x, y, lineheight, spacing);
+ }
+ else if (luax_istype(L, 2, JIN_GRAPHICS_TTF))
+ {
+ TTF* ttf = p2->getObject<TTF>();
+ ttf->print(*text, x, y, lineheight, spacing);
+ }
+ }
+
+ /* print(string[, font], x, y, lineheight, spacing) */
+ static int l_print(lua_State* L)
+ {
+ unsigned length;
+ const char* str = luax_checklstring(L, 1, &length);
+ Text text(Encode::UTF8, str, length);
+ Proxy* p = (Proxy*)luax_toudata(L, 2);
+ int x = luax_optnumber(L, 3, 0);
+ int y = luax_optnumber(L, 4, 0);
+ int lineheight = luax_optnumber(L, 5, 12);
+ int spacing = luax_optnumber(L, 6, 0);
+ if (luax_istype(L, 2, JIN_GRAPHICS_TEXTUREFONT))
+ {
+ TextureFont* tf = p->getObject<TextureFont>();
+ tf->print(text, x, y, lineheight, spacing);
+ }
+ else if (luax_istype(L, 2, JIN_GRAPHICS_TTF))
+ {
+ TTF* ttf = p->getObject<TTF>();
+ ttf->print(text, x, y, lineheight, spacing);
+ }
+ return 0;
+ }
+
+ /* jin.graphics.draw(page, x, y) */
+ static void l_draw_page(lua_State* L)
+ {
+ if (!luax_istype(L, 1, JIN_GRAPHICS_PAGE))
+ return;
+ int x = luax_optnumber(L, 2, 0);
+ int y = luax_optnumber(L, 3, 0);
+ Proxy* p = (Proxy*)luax_toudata(L, 1);
+ Page* page = p->getObject<Page>();
+ Font* font = page->font;
+ font->print(page, x, y);
+ }
+
static int l_draw(lua_State* L)
{
- int x = luax_optnumber(L, 2, 0);
- int y = luax_optnumber(L, 3, 0);
- float sx = luax_optnumber(L, 4, 1);
- float sy = luax_optnumber(L, 5, 1);
- float r = luax_optnumber(L, 6, 0);
+ if (luax_istype(L, 1, JIN_GRAPHICS_TEXTURE))
+ l_draw_texture(L);
+ else if (luax_istype(L, 1, JIN_GRAPHICS_CANVAS))
+ l_draw_canvas(L);
+ else if (luax_istype(L, 1, JIN_GRAPHICS_TEXT))
+ l_draw_text(L);
+ else if (luax_istype(L, 1, JIN_GRAPHICS_PAGE))
+ l_draw_page(L);
+ else if (luax_isstring(L, 1))
+ l_print(L);
+ else
+ {
+ luax_typerror(L, 1, "texture or canvas");
+ return 1;
+ }
+ return 0;
+ }
+
+ // draw(tex, quad, x, y, sx, sy, r, ax, ay)
+ static int l_drawq(lua_State* L)
+ {
+ if (!luax_istable(L, 2))
+ {
+ luax_typerror(L, 2, "table");
+ return 1;
+ }
+ math::Quad q;
+ q.x = luax_rawgetnumber(L, 2, 1);
+ q.y = luax_rawgetnumber(L, 2, 2);
+ q.w = luax_rawgetnumber(L, 2, 3);
+ q.h = luax_rawgetnumber(L, 2, 4);
+ luax_pop(L, 4);
+ int x = luax_optnumber(L, 3, 0);
+ int y = luax_optnumber(L, 4, 0);
+ float sx = luax_optnumber(L, 5, 1);
+ float sy = luax_optnumber(L, 6, 1);
+ float r = luax_optnumber(L, 7, 0);
+ float ax = luax_optnumber(L, 8, 0);
+ float ay = luax_optnumber(L, 9, 0);
+
if (luax_istype(L, 1, JIN_GRAPHICS_TEXTURE))
{
Proxy* proxy = (Proxy*)luax_toudata(L, 1);
- Ref<Texture>& tex = proxy->getRef<Texture>();
- tex->draw(x, y, sx, sy, r);
+ Ref<Texture>& tex = proxy->getRef<Texture>();
+ tex->draw(q, x, y, sx, sy, r, ax, ay);
}
else if (luax_istype(L, 1, JIN_GRAPHICS_CANVAS))
{
Proxy* proxy = (Proxy*)luax_toudata(L, 1);
Ref<Canvas>& p = proxy->getRef<Canvas>();
- p->draw(x, y, sx, sy, r);
+ p->draw(q, x, y, sx, sy, r, ax, ay);
}
else
{
luax_typerror(L, 1, "texture or canvas");
}
- return 0;
}
static int l_setColor(lua_State* L)
@@ -307,13 +418,7 @@ namespace lua
}
return 0;
}
-/*
- static int l_unuseShader(lua_State* L)
- {
- Shader::unuse();
- return 0;
- }
-*/
+
static int l_setBlend(lua_State* L)
{
@@ -450,10 +555,10 @@ namespace lua
return 0;
}
- static int l_newFontData(lua_State* L)
+ static int l_newTTFData(lua_State* L)
{
- Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_FONTDATA, sizeof(Proxy));
- FontData* fd = nullptr;
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_TTFDATA, sizeof(Proxy));
+ TTFData* fd = nullptr;
{
const char* path = luax_checkstring(L, 1);
Filesystem* fs = Filesystem::get();
@@ -465,52 +570,115 @@ namespace lua
}
Buffer b;
fs->read(path, &b);
- fd = FontData::createFontData((unsigned char*)b.data, b.size);
+ fd = TTFData::createTTFData((unsigned char*)b.data, b.size);
}
- proxy->bind(new Ref<FontData>(fd, JIN_GRAPHICS_FONTDATA));
+ proxy->bind(new Ref<TTFData>(fd, JIN_GRAPHICS_TTFDATA));
return 1;
}
+ /* newText(str[, encode]) */
+ static int l_newText(lua_State* L)
+ {
+ Encode encode = Encode::UTF8;
+ if (luax_gettop(L) == 2)
+ {
+ const char* e = luax_checkstring(L, 2);
+ if (strcmp(e, "UTF8") == 0) encode = Encode::UTF8;
+ //else if (strcmp(e, "UTF16") == 0) encode = Encode::UTF16;
+ else if (strcmp(e, "ASCII") == 0) encode = Encode::ASCII;
+ else
+ {
+ luax_error(L, "wrong text encode %s", e);
+ return 0;
+ }
+ }
+ unsigned length;
+ const char* data = luax_checklstring(L, 1, &length);
+ Text* text = new Text(encode, data, length);
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_TEXT, sizeof(Proxy));
+ proxy->bind(new Ref<Text>(text, JIN_GRAPHICS_TEXT));
+ return 1;
+ }
+
+ /* newTextureFont(bitmap, text, color | cellw, cellh) */
+ static int l_newTextureFont(lua_State* L)
+ {
+ Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_BITMAP);
+ Bitmap* bitmap = p->getObject<Bitmap>();
+ Proxy* pt = (Proxy*)luax_checktype(L, 2, JIN_GRAPHICS_TEXT);
+ Text* text = pt->getObject<Text>();
+ float cellh = luax_checknumber(L, 4);
+ TextureFont* textureFont = nullptr;
+ if (luax_istable(L, 3))
+ {
+ unsigned int r = luax_rawgetnumber(L, 3, 1);
+ unsigned int g = luax_rawgetnumber(L, 3, 2);
+ unsigned int b = luax_rawgetnumber(L, 3, 3);
+ unsigned int a = luax_rawgetnumber(L, 3, 4);
+ textureFont = TextureFont::createTextureFont(bitmap, *text, Color(r, g, b, a), cellh);
+ }
+ else if (luax_isnumber(L, 3))
+ {
+ float cellw = luax_checknumber(L, 3);
+ textureFont = TextureFont::createTextureFont(bitmap, *text, cellw, cellh);
+ }
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_TEXTUREFONT, sizeof(Proxy));
+ proxy->bind(new Ref<TextureFont>(textureFont, JIN_GRAPHICS_TEXTUREFONT));
+ return 1;
+ }
+
+ static int l_setFont(lua_State* L)
+ {
+ return 0;
+ }
+
static const luaL_Reg f[] = {
/* window */
- { "init", l_init },
- { "setTitle", l_setTitle },
- { "getSize", l_getSize },
- { "getWidth", l_getWidth },
- { "getHeight", l_getHeight },
- { "destroy", l_destroy },
+ { "init", l_init },
+ { "setTitle", l_setTitle },
+ { "getSize", l_getSize },
+ { "getWidth", l_getWidth },
+ { "getHeight", l_getHeight },
+ { "destroy", l_destroy },
/* creators */
- { "newBitmap", l_newBitmap },
- { "newTexture", l_newTexture },
- { "newShader", l_newShader },
- { "newCanvas", l_newCanvas },
- { "newFontData", l_newFontData },
+ { "newBitmap", l_newBitmap },
+ { "newTexture", l_newTexture },
+ { "newShader", l_newShader },
+ { "newCanvas", l_newCanvas },
+ { "newTTFData", l_newTTFData },
+ { "newText", l_newText },
+ { "newTextureFont", l_newTextureFont },
/* render */
- { "setClearColor", l_setClearColor },
- { "clear", l_clear },
- { "draw", l_draw },
- { "setColor", l_setColor },
- { "getColor", l_getColor },
- { "present", l_present },
+ { "setClearColor", l_setClearColor },
+ { "clear", l_clear },
+ { "draw", l_draw },
+ { "print", l_print },
+ { "drawq", l_drawq },
+ { "setColor", l_setColor },
+ { "getColor", l_getColor },
+ { "present", l_present },
/* canvas */
- { "bindCanvas", l_bindCanvas },
- { "unbindCanvas", l_unbindCanvas },
+ { "bindCanvas", l_bindCanvas },
+ { "unbindCanvas", l_unbindCanvas },
/* shader */
- { "useShader", l_useShader },
- //{ "unuseShader", l_unuseShader },
+ { "useShader", l_useShader },
/* shapes */
- { "point", l_point },
- { "line", l_line },
- { "rect", l_rect },
- { "circle", l_circle },
- { "triangle", l_triangle },
- { "polygon", l_polygon },
- { 0, 0 }
+ { "point", l_point },
+ { "line", l_line },
+ { "rect", l_rect },
+ { "circle", l_circle },
+ { "triangle", l_triangle },
+ { "polygon", l_polygon },
+ /* font */
+ { "setFont", l_setFont },
+ { 0, 0 }
};
extern int luaopen_Texture(lua_State* L);
- extern int luaopen_Font(lua_State* L);
- extern int luaopen_FontData(lua_State* L);
+ extern int luaopen_Text(lua_State* L);
+ extern int luaopen_TTF(lua_State* L);
+ extern int luaopen_TextureFont(lua_State* L);
+ extern int luaopen_TTFData(lua_State* L);
extern int luaopen_Page(lua_State* L);
extern int luaopen_Canvas(lua_State* L);
extern int luaopen_JSL(lua_State* L);
@@ -522,8 +690,10 @@ namespace lua
luaopen_Bitmap(L);
luaopen_Texture(L);
luaopen_Canvas(L);
- luaopen_FontData(L);
- luaopen_Font(L);
+ luaopen_TTFData(L);
+ luaopen_TTF(L);
+ luaopen_Text(L);
+ luaopen_TextureFont(L);
luaopen_Page(L);
luaopen_JSL(L);
@@ -533,5 +703,5 @@ namespace lua
return 1;
}
-}// lua
-}// jin \ No newline at end of file
+}// lua
+}// jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/page.cpp b/src/lua/modules/graphics/page.cpp
index fd96448..c0a3184 100644
--- a/src/lua/modules/graphics/page.cpp
+++ b/src/lua/modules/graphics/page.cpp
@@ -3,6 +3,8 @@
#include "lua/common/common.h"
#include "libjin/jin.h"
+#include <iostream>
+
namespace jin
{
namespace lua
@@ -21,29 +23,35 @@ namespace lua
static int l_gc(lua_State* L)
{
Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_PAGE);
- proxy->release();
+ {
+ /* release font */
+ Ref<Page>* page = &proxy->getRef<Page>();
+ RefBase* font = (RefBase*)page->getUserdata();
+ font->release();
+ }
+ proxy->release();
return 0;
}
static int l_getSize(lua_State* L)
{
Page* page = getPage(L);
- luax_pushinteger(L, page->width);
- luax_pushinteger(L, page->height);
+ luax_pushinteger(L, page->size.w);
+ luax_pushinteger(L, page->size.h);
return 2;
}
static int l_getWidth(lua_State* L)
{
Page* page = getPage(L);
- luax_pushinteger(L, page->width);
+ luax_pushinteger(L, page->size.w);
return 1;
}
static int l_getHeight(lua_State* L)
{
Page* page = getPage(L);
- luax_pushinteger(L, page->height);
+ luax_pushinteger(L, page->size.h);
return 1;
}
diff --git a/src/lua/modules/graphics/text.cpp b/src/lua/modules/graphics/text.cpp
new file mode 100644
index 0000000..c0136cc
--- /dev/null
+++ b/src/lua/modules/graphics/text.cpp
@@ -0,0 +1,32 @@
+#include "lua/modules/luax.h"
+#include "lua/modules/types.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::graphics;
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_TEXT);
+ p->release();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { 0, 0 }
+ };
+
+ int luaopen_Text(lua_State* L)
+ {
+ luax_newtype(L, JIN_GRAPHICS_TEXT, f);
+ return 0;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/textureFont.cpp b/src/lua/modules/graphics/textureFont.cpp
new file mode 100644
index 0000000..4cf5bdd
--- /dev/null
+++ b/src/lua/modules/graphics/textureFont.cpp
@@ -0,0 +1,67 @@
+#include "lua/modules/luax.h"
+#include "lua/modules/types.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::graphics;
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_TEXTUREFONT);
+ proxy->release();
+ return 0;
+ }
+
+ /* typeset(Text | string, lineheight, spacing) */
+ static int l_typeset(lua_State* L)
+ {
+ Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_TEXTUREFONT);
+ TextureFont* tf = p->getObject<TextureFont>();
+ int lineheight = luax_checkinteger(L, 3);
+ int spacing = luax_optnumber(L, 4, 0);
+ Page* page = nullptr;
+ if (luax_isstring(L, 2))
+ {
+ unsigned length;
+ const char* str = luax_checklstring(L, 2, &length);
+ Text text(Encode::UTF8, str, length);
+ page = tf->typeset(text, lineheight, spacing);
+ }
+ else if (luax_istype(L, 2, JIN_GRAPHICS_TEXT))
+ {
+ Proxy* p2 = (Proxy*)luax_checktype(L, 2, JIN_GRAPHICS_TEXT);
+ Text* text = p2->getObject<Text>();
+ page = tf->typeset(*text, lineheight, spacing);
+ }
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_PAGE, sizeof(Proxy));
+ Ref<Page>* refPage = new Ref<Page>(page, JIN_GRAPHICS_PAGE);
+ {
+ /* retain related ttf */
+ Ref<TextureFont>& refTF = p->getRef<TextureFont>();
+ refTF.retain();
+ refPage->setUserdata(&refTF);
+ }
+ proxy->bind(refPage);
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { "typeset", l_typeset },
+ { 0, 0 }
+ };
+
+ int luaopen_TextureFont(lua_State* L)
+ {
+ luax_newtype(L, JIN_GRAPHICS_TEXTUREFONT, f);
+
+ return 0;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/ttf.cpp b/src/lua/modules/graphics/ttf.cpp
new file mode 100644
index 0000000..19e9e92
--- /dev/null
+++ b/src/lua/modules/graphics/ttf.cpp
@@ -0,0 +1,73 @@
+#include "lua/modules/luax.h"
+#include "lua/modules/types.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::graphics;
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* proxy = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_TTF);
+ {
+ /* release ttf data */
+ Ref<TTF>* ttf = &proxy->getRef<TTF>();
+ RefBase* data = (RefBase*)ttf->getUserdata();
+ data->release();
+ }
+ proxy->release();
+ return 0;
+ }
+
+ /* typeset(Text | string, lineheight, spacing) */
+ static int l_typeset(lua_State* L)
+ {
+ Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_TTF);
+ TTF* ttf = p->getObject<TTF>();
+ int lineheight = luax_checkinteger(L, 3);
+ int spacing = luax_optnumber(L, 4, 0);
+ Page* page = nullptr;
+ if (luax_isstring(L, 2))
+ {
+ unsigned length;
+ const char* str = luax_checklstring(L, 2, &length);
+ Text text(Encode::UTF8, str, length);
+ page = ttf->typeset(text, lineheight, spacing);
+ }
+ else if (luax_istype(L, 2, JIN_GRAPHICS_TEXT))
+ {
+ Proxy* p2 = (Proxy*)luax_checktype(L, 2, JIN_GRAPHICS_TEXT);
+ Text* text = p2->getObject<Text>();
+ page = ttf->typeset(*text, lineheight, spacing);
+ }
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_PAGE, sizeof(Proxy));
+ Ref<Page>* refPage = new Ref<Page>(page, JIN_GRAPHICS_PAGE);
+ {
+ /* retain related ttf */
+ Ref<TTF>& refTTF = p->getRef<TTF>();
+ refTTF.retain();
+ refPage->setUserdata(&refTTF);
+ }
+ proxy->bind(refPage);
+ return 1;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { "typeset", l_typeset },
+ { 0, 0 }
+ };
+
+ int luaopen_TTF(lua_State* L)
+ {
+ luax_newtype(L, JIN_GRAPHICS_TTF, f);
+
+ return 0;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/graphics/ttfData.cpp b/src/lua/modules/graphics/ttfData.cpp
new file mode 100644
index 0000000..26cd784
--- /dev/null
+++ b/src/lua/modules/graphics/ttfData.cpp
@@ -0,0 +1,51 @@
+#include "lua/modules/luax.h"
+#include "lua/modules/types.h"
+#include "lua/common/common.h"
+#include "libjin/jin.h"
+
+namespace jin
+{
+namespace lua
+{
+
+ using namespace jin::graphics;
+
+ static int l_newTTF(lua_State* L)
+ {
+ Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_TTFDATA);
+ int fontsize = luax_checkinteger(L, 2);
+ Ref<TTFData>& refFontData = p->getRef<TTFData>();
+ TTFData* fontData = refFontData.getObject();
+ Proxy* proxy = (Proxy*)luax_newinstance(L, JIN_GRAPHICS_TTF, sizeof(Proxy));
+ TTF* font = TTF::createTTF(fontData, fontsize);
+ Ref<TTF>* refTTF = new Ref<TTF>(font, JIN_GRAPHICS_TTF);
+ {
+ Ref<TTFData>& refTTFData = p->getRef<TTFData>();
+ refTTFData.retain();
+ refTTF->setUserdata(&refTTFData);
+ }
+ proxy->bind(refTTF);
+ return 1;
+ }
+
+ static int l_gc(lua_State* L)
+ {
+ Proxy* p = (Proxy*)luax_checktype(L, 1, JIN_GRAPHICS_TTFDATA);
+ p->release();
+ return 0;
+ }
+
+ static const luaL_Reg f[] = {
+ { "__gc", l_gc },
+ { "newTTF", l_newTTF },
+ { 0, 0 }
+ };
+
+ int luaopen_TTFData(lua_State* L)
+ {
+ luax_newtype(L, JIN_GRAPHICS_TTFDATA, f);
+ return 0;
+ }
+
+} // lua
+} // jin \ No newline at end of file
diff --git a/src/lua/modules/types.h b/src/lua/modules/types.h
index 5f9f0bb..dcf3631 100644
--- a/src/lua/modules/types.h
+++ b/src/lua/modules/types.h
@@ -1,14 +1,16 @@
#ifndef __JIN_MODULES_TYPES_H
#define __JIN_MODULES_TYPES_H
-// graphics module
-#define JIN_GRAPHICS_TEXTURE "Texture"
-#define JIN_GRAPHICS_SHADER "Shader"
-#define JIN_GRAPHICS_CANVAS "Canvas"
-#define JIN_GRAPHICS_FONTDATA "FontData"
-#define JIN_GRAPHICS_FONT "Font"
-#define JIN_GRAPHICS_PAGE "Page"
-#define JIN_GRAPHICS_BITMAP "Bitmap"
+// graphics module
+#define JIN_GRAPHICS_TEXTURE "Texture"
+#define JIN_GRAPHICS_SHADER "Shader"
+#define JIN_GRAPHICS_CANVAS "Canvas"
+#define JIN_GRAPHICS_TEXT "Text"
+#define JIN_GRAPHICS_TTFDATA "TTFData"
+#define JIN_GRAPHICS_TTF "TTF"
+#define JIN_GRAPHICS_TEXTUREFONT "TextureFont"
+#define JIN_GRAPHICS_PAGE "Page"
+#define JIN_GRAPHICS_BITMAP "Bitmap"
// audio module
#define JIN_AUDIO_SOURCE "Source"