aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2018-10-10 13:10:23 +0800
committerchai <chaifix@163.com>2018-10-10 13:10:23 +0800
commit498664ceba42e3b609e4464c246de164c61775c7 (patch)
treec1741b8ba567d5d0aafef7831298bdddb348b7d7
parent95c088f3e48321c155eabc00fc4710692405855d (diff)
*update
-rw-r--r--build/Debug/05Font.exebin1194496 -> 1091072 bytes
-rw-r--r--build/libjin.sln11
-rw-r--r--build/libjin/libjin.vcxproj8
-rw-r--r--build/libjin/libjin.vcxproj.filters30
-rw-r--r--libjin/3rdparty/ogl/OpenGL.h9
-rw-r--r--libjin/Audio/SDL/SDLSource.cpp16
-rw-r--r--libjin/Game/Game.cpp32
-rw-r--r--libjin/Graphics/Bitmap.h1
-rw-r--r--libjin/Graphics/Drawable.cpp69
-rw-r--r--libjin/Graphics/Drawable.h6
-rw-r--r--libjin/Graphics/Font.cpp354
-rw-r--r--libjin/Graphics/Font.h99
-rw-r--r--libjin/Graphics/FontData.cpp115
-rw-r--r--libjin/Graphics/FontData.h45
-rw-r--r--libjin/Graphics/Graphics.h3
-rw-r--r--libjin/Graphics/Mesh.h4
-rw-r--r--libjin/Graphics/Page.h38
-rw-r--r--libjin/Graphics/Shader.cpp34
-rw-r--r--libjin/Graphics/Shader.h10
-rw-r--r--libjin/Graphics/Shaders/base.shader.h48
-rw-r--r--libjin/Graphics/Shapes.cpp35
-rw-r--r--libjin/Graphics/TTF.cpp458
-rw-r--r--libjin/Graphics/TTF.h114
-rw-r--r--libjin/Graphics/TexFont.cpp56
-rw-r--r--libjin/Graphics/TexFont.h44
-rw-r--r--libjin/Graphics/Texture.cpp12
-rw-r--r--libjin/Graphics/Window.cpp2
-rw-r--r--libjin/Math/Matrix.cpp4
-rw-r--r--test/05Font/main.cpp70
-rw-r--r--test/06TextureFont/main.cpp3
30 files changed, 971 insertions, 759 deletions
diff --git a/build/Debug/05Font.exe b/build/Debug/05Font.exe
index cf80b7f..7b9484a 100644
--- a/build/Debug/05Font.exe
+++ b/build/Debug/05Font.exe
Binary files differ
diff --git a/build/libjin.sln b/build/libjin.sln
index 05a6517..59694f9 100644
--- a/build/libjin.sln
+++ b/build/libjin.sln
@@ -17,6 +17,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{D4
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "05Font", "05Font\05Font.vcxproj", "{D1953718-E728-4A86-9CCF-8BEC1F5C5F97}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "06TextureFont", "06TextureFont\06TextureFont.vcxproj", "{A81B426C-A6C7-4861-92A9-A087872D2C53}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@@ -73,6 +75,14 @@ Global
{D1953718-E728-4A86-9CCF-8BEC1F5C5F97}.Release|x64.Build.0 = Release|x64
{D1953718-E728-4A86-9CCF-8BEC1F5C5F97}.Release|x86.ActiveCfg = Release|Win32
{D1953718-E728-4A86-9CCF-8BEC1F5C5F97}.Release|x86.Build.0 = Release|Win32
+ {A81B426C-A6C7-4861-92A9-A087872D2C53}.Debug|x64.ActiveCfg = Debug|x64
+ {A81B426C-A6C7-4861-92A9-A087872D2C53}.Debug|x64.Build.0 = Debug|x64
+ {A81B426C-A6C7-4861-92A9-A087872D2C53}.Debug|x86.ActiveCfg = Debug|Win32
+ {A81B426C-A6C7-4861-92A9-A087872D2C53}.Debug|x86.Build.0 = Debug|Win32
+ {A81B426C-A6C7-4861-92A9-A087872D2C53}.Release|x64.ActiveCfg = Release|x64
+ {A81B426C-A6C7-4861-92A9-A087872D2C53}.Release|x64.Build.0 = Release|x64
+ {A81B426C-A6C7-4861-92A9-A087872D2C53}.Release|x86.ActiveCfg = Release|Win32
+ {A81B426C-A6C7-4861-92A9-A087872D2C53}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -83,6 +93,7 @@ Global
{0E49D105-2032-4825-9FA1-54B1B94E3655} = {D401F737-EEF5-4EA3-8CEA-A15523AE68AD}
{85071432-24B6-46D4-98D8-DAA63183093C} = {D401F737-EEF5-4EA3-8CEA-A15523AE68AD}
{D1953718-E728-4A86-9CCF-8BEC1F5C5F97} = {D401F737-EEF5-4EA3-8CEA-A15523AE68AD}
+ {A81B426C-A6C7-4861-92A9-A087872D2C53} = {D401F737-EEF5-4EA3-8CEA-A15523AE68AD}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {310E7948-2690-4896-9579-19E6AC4D405B}
diff --git a/build/libjin/libjin.vcxproj b/build/libjin/libjin.vcxproj
index ebd95dc..f186a79 100644
--- a/build/libjin/libjin.vcxproj
+++ b/build/libjin/libjin.vcxproj
@@ -36,8 +36,8 @@
<ClCompile Include="..\..\libjin\Graphics\Canvas.cpp" />
<ClCompile Include="..\..\libjin\Graphics\Color.cpp" />
<ClCompile Include="..\..\libjin\Graphics\Drawable.cpp" />
- <ClCompile Include="..\..\libjin\Graphics\Font.cpp" />
- <ClCompile Include="..\..\libjin\Graphics\FontData.cpp" />
+ <ClCompile Include="..\..\libjin\Graphics\TexFont.cpp" />
+ <ClCompile Include="..\..\libjin\Graphics\TTF.cpp" />
<ClCompile Include="..\..\libjin\Graphics\Mesh.cpp" />
<ClCompile Include="..\..\libjin\Graphics\OpenGL.cpp" />
<ClCompile Include="..\..\libjin\Graphics\Shader.cpp" />
@@ -87,11 +87,12 @@
<ClInclude Include="..\..\libjin\Graphics\Canvas.h" />
<ClInclude Include="..\..\libjin\Graphics\Color.h" />
<ClInclude Include="..\..\libjin\Graphics\Drawable.h" />
+ <ClInclude Include="..\..\libjin\Graphics\TTF.h" />
<ClInclude Include="..\..\libjin\Graphics\Font.h" />
- <ClInclude Include="..\..\libjin\Graphics\FontData.h" />
<ClInclude Include="..\..\libjin\Graphics\Graphics.h" />
<ClInclude Include="..\..\libjin\Graphics\Mesh.h" />
<ClInclude Include="..\..\libjin\Graphics\OpenGL.h" />
+ <ClInclude Include="..\..\libjin\Graphics\Page.h" />
<ClInclude Include="..\..\libjin\Graphics\Shader.h" />
<ClInclude Include="..\..\libjin\Graphics\Shaders\base.shader.h" />
<ClInclude Include="..\..\libjin\Graphics\Shaders\default.shader.h" />
@@ -99,6 +100,7 @@
<ClInclude Include="..\..\libjin\Graphics\Shaders\texture.shader.h" />
<ClInclude Include="..\..\libjin\Graphics\Shapes.h" />
<ClInclude Include="..\..\libjin\Graphics\Texture.h" />
+ <ClInclude Include="..\..\libjin\Graphics\TexFont.h" />
<ClInclude Include="..\..\libjin\Graphics\Utf8.h" />
<ClInclude Include="..\..\libjin\Graphics\Window.h" />
<ClInclude Include="..\..\libjin\Input\Event.h" />
diff --git a/build/libjin/libjin.vcxproj.filters b/build/libjin/libjin.vcxproj.filters
index f79e814..cd91c37 100644
--- a/build/libjin/libjin.vcxproj.filters
+++ b/build/libjin/libjin.vcxproj.filters
@@ -99,9 +99,6 @@
<ClCompile Include="..\..\libjin\Graphics\Drawable.cpp">
<Filter>Graphics</Filter>
</ClCompile>
- <ClCompile Include="..\..\libjin\Graphics\Font.cpp">
- <Filter>Graphics</Filter>
- </ClCompile>
<ClCompile Include="..\..\libjin\Graphics\Texture.cpp">
<Filter>Graphics</Filter>
</ClCompile>
@@ -162,9 +159,6 @@
<ClCompile Include="..\..\libjin\Game\Game.cpp">
<Filter>Game</Filter>
</ClCompile>
- <ClCompile Include="..\..\libjin\Graphics\FontData.cpp">
- <Filter>Graphics</Filter>
- </ClCompile>
<ClCompile Include="..\..\libjin\Graphics\Mesh.cpp">
<Filter>Graphics</Filter>
</ClCompile>
@@ -174,6 +168,12 @@
<ClCompile Include="..\..\libjin\Graphics\Utf8.cpp">
<Filter>Graphics</Filter>
</ClCompile>
+ <ClCompile Include="..\..\libjin\Graphics\TTF.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\libjin\Graphics\TexFont.cpp">
+ <Filter>Graphics</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\libjin\3rdparty\GLee\GLee.h">
@@ -230,9 +230,6 @@
<ClInclude Include="..\..\libjin\Graphics\Drawable.h">
<Filter>Graphics</Filter>
</ClInclude>
- <ClInclude Include="..\..\libjin\Graphics\Font.h">
- <Filter>Graphics</Filter>
- </ClInclude>
<ClInclude Include="..\..\libjin\Graphics\Graphics.h">
<Filter>Graphics</Filter>
</ClInclude>
@@ -340,9 +337,6 @@
<ClInclude Include="..\..\libjin\Math\Vector4.hpp">
<Filter>Math</Filter>
</ClInclude>
- <ClInclude Include="..\..\libjin\Graphics\FontData.h">
- <Filter>Graphics</Filter>
- </ClInclude>
<ClInclude Include="..\..\libjin\Graphics\OpenGL.h">
<Filter>Graphics</Filter>
</ClInclude>
@@ -367,6 +361,18 @@
<ClInclude Include="..\..\libjin\Graphics\Shaders\texture.shader.h">
<Filter>Graphics\Shaders</Filter>
</ClInclude>
+ <ClInclude Include="..\..\libjin\Graphics\Page.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\libjin\Graphics\TTF.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\libjin\Graphics\Font.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\libjin\Graphics\TexFont.h">
+ <Filter>Graphics</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\libjin\README.md" />
diff --git a/libjin/3rdparty/ogl/OpenGL.h b/libjin/3rdparty/ogl/OpenGL.h
index 33b14d2..3984b49 100644
--- a/libjin/3rdparty/ogl/OpenGL.h
+++ b/libjin/3rdparty/ogl/OpenGL.h
@@ -45,15 +45,6 @@ namespace ogl2d
void texImage(GLint internalformat, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels = NULL);
void texSubImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
void activeTexUnit(unsigned int unit = 0);
- inline void vertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
- {
- glVertexPointer(size, type, stride, pointer);
- }
-
- inline void texCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer)
- {
- glTexCoordPointer(size, type, stride, pointer);
- }
inline void drawArrays(GLenum mode, GLint first, GLsizei count)
{
diff --git a/libjin/Audio/SDL/SDLSource.cpp b/libjin/Audio/SDL/SDLSource.cpp
index 251ef27..9f4f2fb 100644
--- a/libjin/Audio/SDL/SDLSource.cpp
+++ b/libjin/Audio/SDL/SDLSource.cpp
@@ -290,21 +290,21 @@ Manager::get()->pushCommand(cmd); \
for (int i = 0; i < samples; ++i)
{
char* source = (char*)raw.data + status.pos * (raw.bitdepth / 8) * raw.channels;
- short left = 0;
- short right = 0;
+ short l = 0;
+ short r = 0;
if (raw.bitdepth == 16)
{
- left = ((short*)source)[L] * status.volume;
- right = ((short*)source)[L + raw.channels - 1] * status.volume;
+ l = ((short*)source)[L] * status.volume;
+ r = ((short*)source)[L + raw.channels - 1] * status.volume;
}
else if (raw.bitdepth == 8)
{
- left = source[L] << 8; // << 8 Ŵ16bits
- right = source[L + raw.channels - 1] << 8;
+ l = source[L] << 8; // << 8 Ŵ16bits
+ r = source[L + raw.channels - 1] << 8;
}
short* sample = buffer + (i << 1);
- sample[L] = clamp(sample[L] + left, SHRT_MIN, SHRT_MAX); //
- sample[R] = clamp(sample[R] + right, SHRT_MIN, SHRT_MAX); //
+ sample[L] = clamp(sample[L] + l, SHRT_MIN, SHRT_MAX); //
+ sample[R] = clamp(sample[R] + r, SHRT_MIN, SHRT_MAX); //
++status.pos;
if (status.pos > raw.samples && status.loop)
status.pos = 0; // rewind
diff --git a/libjin/Game/Game.cpp b/libjin/Game/Game.cpp
index 3f905f2..6dc75ce 100644
--- a/libjin/Game/Game.cpp
+++ b/libjin/Game/Game.cpp
@@ -26,30 +26,26 @@ namespace core
const int MS_PER_UPDATE = 1000.0f / FPS;
_running = true;
Event e;
- int previous = getMilliSecond();
- int dt = MS_PER_UPDATE;
+ int current = getMilliSecond();
+ int previous = current;
+ int dt = 0;
while (_running)
{
while (jin::input::pollEvent(&e))
{
- if (_onEvent != nullptr)
- _onEvent(&e);
- if (!_running) goto quitloop;
+ if (_onEvent != nullptr)
+ _onEvent(&e);
+ if (!_running)
+ goto quitloop;
}
- if (_onUpdate != nullptr) _onUpdate(dt);
- if (_onDraw != nullptr) _onDraw();
- wnd->swapBuffers();
- const int current = getMilliSecond();
+ previous = current;
+ current = getMilliSecond();
dt = current - previous;
- const int wait = MS_PER_UPDATE - (current - previous);
- previous += MS_PER_UPDATE;
- if (wait > 0)
- {
- sleep(wait);
- dt = MS_PER_UPDATE;
- }
- else
- previous = current;
+ if (_onUpdate != nullptr)
+ _onUpdate(dt);
+ if (_onDraw != nullptr)
+ _onDraw();
+ wnd->swapBuffers();
}
quitloop:;
}
diff --git a/libjin/Graphics/Bitmap.h b/libjin/Graphics/Bitmap.h
index af7f376..5510569 100644
--- a/libjin/Graphics/Bitmap.h
+++ b/libjin/Graphics/Bitmap.h
@@ -16,7 +16,6 @@ namespace graphics
public:
static Bitmap* createBitmap(const void* imgData, size_t size);
static Bitmap* createBitmap(int w, int h, Color color = Color::BLACK);
- static void destroyBitmap(Bitmap* bitmap);
static Bitmap* clone(const Bitmap* bitmap);
~Bitmap();
diff --git a/libjin/Graphics/Drawable.cpp b/libjin/Graphics/Drawable.cpp
index 9f52f0a..ee3e5f2 100644
--- a/libjin/Graphics/Drawable.cpp
+++ b/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,35 @@ 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;
+
+ 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);
+ }
+
Drawable::~Drawable()
{
glDeleteTextures(1, &texture);
@@ -42,9 +71,9 @@ namespace graphics
{
gl.ModelMatrix.setTransformation(x, y, r, sx, sy, anchor.x, anchor.y);
- Shader* shader = Shader::getCurrentJSL();
- shader->sendMatrix4(Shader::MODEL_MATRIX, &gl.ModelMatrix);
- shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ Shader* shader = Shader::getCurrentShader();
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
shader->bindVertexPointer(2, GL_FLOAT, 0, vertex_coords);
shader->bindUVPointer(2, GL_FLOAT, 0, texture_coords);
@@ -53,6 +82,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::SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(Shader::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/libjin/Graphics/Drawable.h b/libjin/Graphics/Drawable.h
index c77068c..0c4c3ef 100644
--- a/libjin/Graphics/Drawable.h
+++ b/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/libjin/Graphics/Font.cpp b/libjin/Graphics/Font.cpp
deleted file mode 100644
index dc7fb33..0000000
--- a/libjin/Graphics/Font.cpp
+++ /dev/null
@@ -1,354 +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;
- }
-
- /*static*/ Font* Font::createFont(FontData* fontData, unsigned int fontSzie)
- {
- Font* font;
- try
- {
- font = new Font(fontData, fontSzie);
- }
- catch (...)
- {
- return nullptr;
- }
- return font;
- }
-
- void Font::destroyFont(Font* font)
- {
- if (font != nullptr)
- delete 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::getCurrentJSL();
- 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->getHMetrics(c, &adw, &lsb);
- return adw;
- }
-
- int Font::getCharHeight(int c)
- {
- return descent;
- }
-
- int Font::getTextWidth(const char* t, int spacing)
- {
- 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;
- }
- return res;
- }
-
- int Font::getTextHeight(const char* t, int lineheight)
- {
- 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;
- }
- }
- return res;
- }
-
- void Font::getTextBox(const char* text, int* w, int* h, int lineheight, int spacing)
- {
- *w = 0;
- *h = 0;
- int tmp = 0;
- const char *p = text;
- bool nl = true;
- while (*p) {
- unsigned c;
- p = utf8toCodepoint(p, &c);
- if (*p == 0x0D)
- continue;
- if (*p == 0x0A)
- {
- tmp = 0;
- nl = true;
- continue;
- }
- else if(nl)
- {
- nl = false;
- *h += lineheight;
- }
- tmp += getCharWidth(c) + spacing;
- if (tmp > *w) *w = tmp;
- }
- }
-
- 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/libjin/Graphics/Font.h b/libjin/Graphics/Font.h
index 4525e8f..adb8c38 100644
--- a/libjin/Graphics/Font.h
+++ b/libjin/Graphics/Font.h
@@ -1,105 +1,28 @@
#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;
- };
+ typedef unsigned int Codepoint;
- struct Page
- {
- std::vector<GlyphArrayDrawInfo> glyphinfolist;
- std::vector<GlyphVertex> glyphvertices;
- int width, height;
- };
+ struct Page;
class Font
{
public:
- typedef unsigned int Codepoint;
-
- static Font* createFont(FontData* fontData, unsigned int fontSzie);
- static void destroyFont(Font* font);
-
- 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
-
- 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);
- ~Font();
-
- 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;
+ Font() {}
+ virtual ~Font() {};
- /* cursor helped render to texture */
- math::Vector2<float> cursor;
+ virtual void print(const Page* page, int x, int y) = 0;
+ virtual void print(const std::vector<Codepoint>& text, int x, int y, int lineheight, int spacing = 0) = 0;
+ virtual Page* typeset(const std::vector<Codepoint>& text, int lineheight, int spacing = 0) = 0;
};
-} // graphics
-} // jin
+}
+}
-#endif // LIBJIN_MODULES_RENDER
-#endif // __LIBJIN_FONT_H \ No newline at end of file
+#endif \ No newline at end of file
diff --git a/libjin/Graphics/FontData.cpp b/libjin/Graphics/FontData.cpp
deleted file mode 100644
index 1b66b12..0000000
--- a/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/libjin/Graphics/FontData.h b/libjin/Graphics/FontData.h
deleted file mode 100644
index c75b9a1..0000000
--- a/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/libjin/Graphics/Graphics.h b/libjin/Graphics/Graphics.h
index 961f9b1..a4bf98b 100644
--- a/libjin/Graphics/Graphics.h
+++ b/libjin/Graphics/Graphics.h
@@ -5,7 +5,8 @@
#include "canvas.h"
#include "color.h"
-#include "font.h"
+#include "FontData.h"
+#include "Font.h"
#include "Shapes.h"
#include "texture.h"
#include "Shader.h"
diff --git a/libjin/Graphics/Mesh.h b/libjin/Graphics/Mesh.h
index d0bb93e..c14af89 100644
--- a/libjin/Graphics/Mesh.h
+++ b/libjin/Graphics/Mesh.h
@@ -8,6 +8,10 @@ namespace graphics
class Mesh
{
+ public:
+
+ private:
+
};
diff --git a/libjin/Graphics/Page.h b/libjin/Graphics/Page.h
new file mode 100644
index 0000000..b878a74
--- /dev/null
+++ b/libjin/Graphics/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/libjin/Graphics/Shader.cpp b/libjin/Graphics/Shader.cpp
index d484662..688fa51 100644
--- a/libjin/Graphics/Shader.cpp
+++ b/libjin/Graphics/Shader.cpp
@@ -21,13 +21,7 @@ namespace graphics
* SHADER_FORMAT_SIZE
* formatShader
*/
- #include "Shaders/base.shader.h"
-
- const char* Shader::PROJECTION_MATRIX = "_projectionMatrix_";
- const char* Shader::MODEL_MATRIX = "_modelMatrix_";
- const char* Shader::MAIN_TEXTURE = "_main_texture_";
- const char* Shader::VERTEX_COORDS = "_vert_coord_";
- const char* Shader::TEXTURE_COORDS = "_tex_coord_";
+ #include "Shaders/default.shader.h"
/**
* https://stackoverflow.com/questions/27941496/use-sampler-without-passing-through-value
@@ -85,6 +79,7 @@ namespace graphics
bool Shader::compile(const string& program)
{
+ /* parse shader source, need some optimizations */
int loc_VERTEX_SHADER = program.find("#VERTEX_SHADER");
int loc_END_VERTEX_SHADER = program.find("#END_VERTEX_SHADER");
int loc_FRAGMENT_SHADER = program.find("#FRAGMENT_SHADER");
@@ -95,12 +90,13 @@ namespace graphics
|| loc_END_FRAGMENT_SHADER == string::npos
)
return false;
- int p = loc_VERTEX_SHADER + strlen("#VERTEX_SHADER");
- string vertex_shader = program.substr(p, loc_END_VERTEX_SHADER - p);
+ /* load vertex and fragment shader source into buffers */
+ int start = loc_VERTEX_SHADER + strlen("#VERTEX_SHADER");
+ string vertex_shader = program.substr(start, loc_END_VERTEX_SHADER - start);
Buffer vbuffer = Buffer(vertex_shader.length() + BASE_VERTEX_SHADER_SIZE);
formatVertexShader((char*)vbuffer.data, vertex_shader.c_str());
- p = loc_FRAGMENT_SHADER + strlen("#FRAGMENT_SHADER");
- string fragment_shader = program.substr(p, loc_END_FRAGMENT_SHADER - p);
+ start = loc_FRAGMENT_SHADER + strlen("#FRAGMENT_SHADER");
+ string fragment_shader = program.substr(start, loc_END_FRAGMENT_SHADER - start);
Buffer fbuffer = Buffer(fragment_shader.length() + BASE_FRAGMENT_SHADER_SIZE);
formatFragmentShader((char*)fbuffer.data, fragment_shader.c_str());
/* compile */
@@ -109,18 +105,12 @@ namespace graphics
glShaderSource(vshader, 1, (const GLchar**)&vbuffer.data, NULL);
glCompileShader(vshader);
glGetShaderiv(vshader, GL_COMPILE_STATUS, &success);
- std::cout << (char*)vbuffer.data << std::endl;
- Buffer log = Buffer(1024);
- int len;
- glGetShaderInfoLog(vshader, sizeof(log), &len, (GLchar*)log.data);
- std::cout << (char*)log.data << std::endl;
if (success == GL_FALSE)
return false;
GLuint fshader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fshader, 1, (const GLchar**)&fbuffer.data, NULL);
glCompileShader(fshader);
glGetShaderiv(fshader, GL_COMPILE_STATUS, &success);
- std::cout << (char*)fbuffer.data << std::endl;
if (success == GL_FALSE)
return false;
pid = glCreateProgram();
@@ -128,8 +118,6 @@ namespace graphics
glAttachShader(pid, fshader);
glLinkProgram(pid);
glGetProgramiv(pid, GL_LINK_STATUS, &success);
- glGetProgramInfoLog(pid, 1024, &len, (GLchar*)log.data);
- std::cout << (char*)log.data << std::endl;
if (success == GL_FALSE)
throw false;
}
@@ -140,12 +128,12 @@ namespace graphics
glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTextureUnits);
return maxTextureUnits;
}
-
+
void Shader::use()
{
glUseProgram(pid);
currentShader = this;
- sendInt(Shader::MAIN_TEXTURE, DEFAULT_TEXTURE_UNIT);
+ sendInt(SHADER_MAIN_TEXTURE, DEFAULT_TEXTURE_UNIT);
}
/*static*/ void Shader::unuse()
@@ -276,14 +264,14 @@ namespace graphics
void Shader::bindVertexPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers)
{
- GLint loc = glGetAttribLocation(pid, VERTEX_COORDS);
+ GLint loc = glGetAttribLocation(pid, SHADER_VERTEX_COORDS);
glEnableVertexAttribArray(0);
glVertexAttribPointer(loc, n, type, GL_FALSE, stride, pointers);
}
void Shader::bindUVPointer(int n, GLenum type, GLsizei stride, const GLvoid * pointers)
{
- GLint loc = glGetAttribLocation(pid, TEXTURE_COORDS);
+ GLint loc = glGetAttribLocation(pid, SHADER_TEXTURE_COORDS);
glEnableVertexAttribArray(1);
glVertexAttribPointer(loc, n, type, GL_FALSE, stride, pointers);
}
diff --git a/libjin/Graphics/Shader.h b/libjin/Graphics/Shader.h
index 2ea9e04..dcd0b62 100644
--- a/libjin/Graphics/Shader.h
+++ b/libjin/Graphics/Shader.h
@@ -9,26 +9,20 @@
#include "texture.h"
#include "canvas.h"
#include "../3rdparty/GLee/GLee.h"
+#include "Shaders/base.shader.h"
namespace jin
{
namespace graphics
{
- /* Jin Shading Language Program*/
class Shader
{
public:
static Shader* createShader(const std::string& program);
- static inline Shader* getCurrentJSL() { return currentShader; }
+ static inline Shader* getCurrentShader() { return currentShader; }
static void unuse();
- static const char* PROJECTION_MATRIX;
- static const char* MODEL_MATRIX;
- static const char* MAIN_TEXTURE;
- static const char* VERTEX_COORDS;
- static const char* TEXTURE_COORDS;
-
virtual ~Shader();
void use();
diff --git a/libjin/Graphics/Shaders/base.shader.h b/libjin/Graphics/Shaders/base.shader.h
index 4efbab7..bf41c4f 100644
--- a/libjin/Graphics/Shaders/base.shader.h
+++ b/libjin/Graphics/Shaders/base.shader.h
@@ -1,3 +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
@@ -51,26 +53,26 @@ static const char* base_vertex = R"(
%s
-uniform mat4 _projectionMatrix_;
-uniform mat4 _modelMatrix_;
+uniform mat4 jin_ProjectionMatrix;
+uniform mat4 jin_ModelMatrix;
-in vec2 _vert_coord_;
-in vec2 _tex_coord_;
+in vec2 jin_VertexCoords;
+in vec2 jin_TextureCoords;
-out vec4 _color;
-out vec2 _xy;
-out vec2 _uv;
+out vec4 jin_Color;
+out vec2 jin_XY;
+out vec2 jin_UV;
%s
void main()
{
- vec4 v = _modelMatrix_ * vec4(_vert_coord_, 0, 1.0);
- Vertex _v = vert(Vertex(v.xy, _tex_coord_));
- gl_Position = _projectionMatrix_ * v;
- _color = gl_Color;
- _xy = _v.xy;
- _uv = _v.uv;
+ vec4 v = jin_ModelMatrix * vec4(jin_VertexCoords, 0, 1.0);
+ Vertex _v = vert(Vertex(v.xy, jin_TextureCoords));
+ gl_Position = jin_ProjectionMatrix * vec4(_v.xy, 0, 1.0f);
+ jin_Color = gl_Color;
+ jin_XY = _v.xy;
+ jin_UV = _v.uv;
}
)";
@@ -83,22 +85,30 @@ static const char* base_fragment = R"(
%s
-uniform Texture _main_texture_;
+uniform Texture jin_MainTexture;
-in vec4 _color;
-in vec2 _xy;
-in vec2 _uv;
+in vec4 jin_Color;
+in vec2 jin_XY;
+in vec2 jin_UV;
-out vec4 _outColor_;
+out vec4 jin_OutColor;
%s
void main()
{
- _outColor_ = frag(_color, _main_texture_, Vertex(_xy, _uv));
+ jin_OutColor = frag(jin_Color, jin_MainTexture, Vertex(jin_XY, jin_UV));
}
)";
static const int BASE_FRAGMENT_SHADER_SIZE = strlen(base_fragment) + BASE_SHARED_SIZE;
#define formatFragmentShader(buf, program) sprintf(buf, base_fragment, base_shared, program)
+
+static const char* SHADER_PROJECTION_MATRIX = "jin_ProjectionMatrix";
+static const char* SHADER_MODEL_MATRIX = "jin_ModelMatrix";
+static const char* SHADER_MAIN_TEXTURE = "jin_MainTexture";
+static const char* SHADER_VERTEX_COORDS = "jin_VertexCoords";
+static const char* SHADER_TEXTURE_COORDS = "jin_TextureCoords";
+
+#endif \ No newline at end of file
diff --git a/libjin/Graphics/Shapes.cpp b/libjin/Graphics/Shapes.cpp
index f639695..f5aedd4 100644
--- a/libjin/Graphics/Shapes.cpp
+++ b/libjin/Graphics/Shapes.cpp
@@ -18,20 +18,22 @@ namespace graphics
{
float verts[] = { x + 0.5f , y + 0.5f };
- Shader* shader = Shader::getCurrentJSL();
+ Shader* shader = Shader::getCurrentShader();
shader->bindVertexPointer(2, GL_FLOAT, 0, verts);
- shader->sendMatrix4(Shader::MODEL_MATRIX, &Matrix::Identity);
- shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ gl.ModelMatrix.setIdentity();
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
glDrawArrays(GL_POINTS, 0, 1);
}
void points(int n, GLshort* p)
{
- Shader* shader = Shader::getCurrentJSL();
+ Shader* shader = Shader::getCurrentShader();
shader->bindVertexPointer(2, GL_SHORT, 0, p);
- shader->sendMatrix4(Shader::MODEL_MATRIX, &Matrix::Identity);
- shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ gl.ModelMatrix.setIdentity();
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
glDrawArrays(GL_POINTS, 0, n);
}
@@ -43,10 +45,11 @@ namespace graphics
x2, y2
};
- Shader* shader = Shader::getCurrentJSL();
+ Shader* shader = Shader::getCurrentShader();
shader->bindVertexPointer(2, GL_FLOAT, 0, verts);
- shader->sendMatrix4(Shader::MODEL_MATRIX, &Matrix::Identity);
- shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ gl.ModelMatrix.setIdentity();
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
glDrawArrays(GL_LINES, 0, 2);
}
@@ -90,9 +93,10 @@ namespace graphics
void polygon_line(float* p, int count)
{
- Shader* shader = Shader::getCurrentJSL();
- shader->sendMatrix4(Shader::MODEL_MATRIX, &Matrix::Identity);
- shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ Shader* shader = Shader::getCurrentShader();
+ gl.ModelMatrix.setIdentity();
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
shader->bindVertexPointer(2, GL_FLOAT, 0, p);
glDrawArrays(GL_LINE_LOOP, 0, count);
@@ -106,9 +110,10 @@ namespace graphics
}
else if (mode == FILL)
{
- Shader* shader = Shader::getCurrentJSL();
- shader->sendMatrix4(Shader::MODEL_MATRIX, &Matrix::Identity);
- shader->sendMatrix4(Shader::PROJECTION_MATRIX, &gl.ProjectionMatrix);
+ Shader* shader = Shader::getCurrentShader();
+ gl.ModelMatrix.setIdentity();
+ shader->sendMatrix4(SHADER_MODEL_MATRIX, &gl.ModelMatrix);
+ shader->sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.ProjectionMatrix);
shader->bindVertexPointer(2, GL_FLOAT, 0, p);
glDrawArrays(GL_POLYGON, 0, count);
diff --git a/libjin/Graphics/TTF.cpp b/libjin/Graphics/TTF.cpp
new file mode 100644
index 0000000..e5a3f3a
--- /dev/null
+++ b/libjin/Graphics/TTF.cpp
@@ -0,0 +1,458 @@
+#include "../jin_configuration.h"
+#if LIBJIN_MODULES_RENDER
+
+#include "OpenGL.h"
+#include "ttf.h"
+#include <stdio.h>
+#include "color.h"
+#include "Shader.h"
+#include "Page.h"
+#include "../Common/Array.hpp"
+
+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()
+ {
+ map<unsigned int, TTFGlyph*>::iterator it = glyphs.begin();
+ for (; it != glyphs.end(); ++it)
+ {
+ delete it->second;
+ }
+ }
+
+ 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 std::vector<Codepoint>& t, int x, int y, int lineheight, int spacing)
+ {
+ Page* page = typeset(t, lineheight, spacing);
+ print(page, x, y);
+ delete page;
+ }
+
+ Page* TTF::typeset(const std::vector<Codepoint>& 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;
+#define glyphvertices_push(_x, _y, _u, _v) \
+vertex.x = _x; vertex.y = _y;\
+vertex.u = _u; vertex.v = _v;\
+glyphvertices.push_back(vertex);
+ Vector2<int> p(0, 0);
+ int i = 0;
+ for (Codepoint c : text)
+ {
+ if (c == 0x0D)
+ continue;
+ /* new line */
+ if (c == 0x0A)
+ {
+ p.y += lineheight;
+ p.x = 0;
+ 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;
+ 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.height);
+ glyphvertices_push(p.x + glyph->width, p.y + glyph->height, bbox.x + bbox.width, bbox.y + bbox.height);
+ glyphvertices_push(p.x + glyph->width, p.y, bbox.x + bbox.width, bbox.y);
+
+ p.x += glyph->width + spacing;
+
+ i += 4;
+ }
+#undef glyphvertices_push
+ getTextBox(text, &page->size.w, &page->size.h, lineheight, spacing);
+ return page;
+ }
+
+ 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);
+ }
+ }
+
+ 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 std::vector<Codepoint>& 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 std::vector<Codepoint>& 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 std::vector<Codepoint>& 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)
+ {
+ TTFGlyph* glyph = (TTFGlyph*)malloc(sizeof(TTFGlyph));
+ 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;
+ }
+ 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, TTFGlyph*>(character, glyph));
+
+ cursor.x += adw;
+ return glyph;
+ }
+
+ TTF::TTFGlyph* TTF::findGlyph(unsigned int character)
+ {
+ map<unsigned int, TTFGlyph*>::iterator it = glyphs.find(character);
+ if (it != glyphs.end())
+ {
+ return it->second;
+ }
+ else
+ {
+ TTFGlyph* glyph = bakeGlyph(character);
+ return glyph;
+ }
+ }
+
+} // graphics
+} // jin
+
+#endif // LIBJIN_MODULES_RENDER \ No newline at end of file
diff --git a/libjin/Graphics/TTF.h b/libjin/Graphics/TTF.h
new file mode 100644
index 0000000..d2459ba
--- /dev/null
+++ b/libjin/Graphics/TTF.h
@@ -0,0 +1,114 @@
+#ifndef __LIBJIN_TTF_H
+#define __LIBJIN_TTF_H
+#include "../jin_configuration.h"
+#if LIBJIN_MODULES_RENDER
+
+#include <vector>
+#include <map>
+#include "drawable.h"
+#include "../math/quad.h"
+#include "Page.h"
+#include "Font.h"
+#include "Color.h"
+#include "../3rdparty/stb/stb_truetype.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ 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 std::vector<Codepoint>& text, int lineheight, int spacing) override;
+ void print(const std::vector<Codepoint>& text, int x, int y, int lineheight, int spacing = 0) override;
+ void print(const Page* page, int x, int y) override ;
+#if defined(ttf_debug)
+ void drawAtlas();
+#endif
+ ~TTF();
+
+ private:
+ struct TTFGlyph
+ {
+ GLuint atlas;
+ /* normalized coordinates */
+ struct Bbox
+ {
+ float x, y;
+ float width, height;
+ } 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 std::vector<Codepoint>& text, int spacing = 0);
+ int getTextHeight(const std::vector<Codepoint>& text, int lineheight);
+ void getTextBox(const std::vector<Codepoint>& 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, 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/libjin/Graphics/TexFont.cpp b/libjin/Graphics/TexFont.cpp
new file mode 100644
index 0000000..ffd8c72
--- /dev/null
+++ b/libjin/Graphics/TexFont.cpp
@@ -0,0 +1,56 @@
+#include "TexFont.h"
+
+namespace jin
+{
+namespace graphics
+{
+ /*
+ * +--------------------+
+ * | top |
+ * | l ************* r |
+ * | e ************* i |
+ * | f ****glyphs*** g |
+ * | t ************* h |
+ * | ************* t |
+ * | bottom |
+ * +--------------------+
+ */
+
+ /* create texture font from tilemap */
+ TexFont * TexFont::createTexFont(const Bitmap* bitmap, const std::vector<Codepoint>& codepoints, int cellw, int cellh, int l, int r, int t, int b)
+ {
+ }
+
+ /* create texture font from seperated glyphs */
+ TexFont* TexFont::createTexFont(const Bitmap* bitmap, const std::vector<Codepoint>& codepoints, Color mask, int cellh, int l, int r, int t, int b)
+ {
+
+ }
+
+ TexFont::~TexFont()
+ {
+
+ }
+
+ Page* TexFont::typeset(const std::vector<Codepoint>& text, int lineheight, int spacing = 0)
+ {
+
+ }
+
+ void TexFont::print(const Page* page, int x, int y)
+ {
+
+ }
+
+ void TexFont::print(const std::vector<Codepoint>& text, int x, int y, int linehgiht, int spacing = 0)
+ {
+
+ }
+
+ TexFont::TexFont(const Bitmap* bitmap)
+ : Drawable(bitmap)
+ {
+ }
+
+}
+} \ No newline at end of file
diff --git a/libjin/Graphics/TexFont.h b/libjin/Graphics/TexFont.h
new file mode 100644
index 0000000..334ff5c
--- /dev/null
+++ b/libjin/Graphics/TexFont.h
@@ -0,0 +1,44 @@
+#ifndef __LIBJIN_TEXTURE_FONT_H
+#define __LIBJIN_TEXTURE_FONT_H
+
+#include <map>
+#include <vector>
+
+#include "Page.h"
+#include "Bitmap.h"
+#include "Font.h"
+#include "Drawable.h"
+
+namespace jin
+{
+namespace graphics
+{
+
+ class TexFont : public Font
+ , public Drawable
+ {
+ public:
+ /* create texture font from tilemap */
+ TexFont * createTexFont(const Bitmap* bitmap, const std::vector<Codepoint>& codepoints, int cellw, int cellh, int l = 0, int r = 0, int t = 0, int b = 0);
+ /* create texture font from seperated glyphs */
+ TexFont* createTexFont(const Bitmap* bitmap, const std::vector<Codepoint>& codepoints, Color mask, int cellh, int l = 0, int r = 0, int t = 0, int b = 0);
+
+ ~TexFont();
+
+ Page* typeset(const std::vector<Codepoint>& text, int lineheight, int spacing = 0) override ;
+ void print(const Page* page, int x, int y) override;
+ void print(const std::vector<Codepoint>& text, int x, int y, int linehgiht, int spacing = 0) override;
+
+ private:
+ struct TexGlyph { unsigned short x, y, w, h;};
+
+ TexFont(const Bitmap* bitmap);
+
+ std::map<Codepoint, TexGlyph> glyphs;
+
+ };
+
+}
+}
+
+#endif \ No newline at end of file
diff --git a/libjin/Graphics/Texture.cpp b/libjin/Graphics/Texture.cpp
index 5a39f77..a42e796 100644
--- a/libjin/Graphics/Texture.cpp
+++ b/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/libjin/Graphics/Window.cpp b/libjin/Graphics/Window.cpp
index d04a1c7..6ebc9f9 100644
--- a/libjin/Graphics/Window.cpp
+++ b/libjin/Graphics/Window.cpp
@@ -5,6 +5,7 @@
#include "window.h"
#include "OpenGL.h"
#include "canvas.h"
+#include "Shader.h"
#include "../utils/utils.h"
#include "../audio/sdl/SDLAudio.h"
#include "../utils/log.h"
@@ -77,6 +78,7 @@ namespace graphics
swapBuffers();
/* bind to default canvas */
Canvas::unbind();
+ Shader::unuse();
return true;
}
diff --git a/libjin/Math/Matrix.cpp b/libjin/Math/Matrix.cpp
index a80f37a..a6e2491 100644
--- a/libjin/Math/Matrix.cpp
+++ b/libjin/Math/Matrix.cpp
@@ -26,10 +26,10 @@ namespace math
void Matrix::setOrtho(float l, float r, float b, float t, float n, float f)
{
- float w = r - l;
+ setIdentity();
+ float w = r - l;
float h = t - b;
float z = f - n;
- setIdentity();
e[0] = 2 / w;
e[5] = 2 / h;
e[10] = -2 / z;
diff --git a/test/05Font/main.cpp b/test/05Font/main.cpp
index 3b58bae..3ce8183 100644
--- a/test/05Font/main.cpp
+++ b/test/05Font/main.cpp
@@ -10,13 +10,14 @@ Font* font = nullptr;
Canvas* canvas;
FontData* data = nullptr;
Shader* shader = nullptr;
+Shader* shader2 = nullptr;
Page* page = nullptr;
Texture* tex = nullptr;
float dt;
void onLoad()
{
- const char* program = R"(
+ const char* font_shader = R"(
#VERTEX_SHADER
Vertex vert(Vertex v)
@@ -28,8 +29,6 @@ Vertex vert(Vertex v)
#FRAGMENT_SHADER
-vec2 stepSize = vec2(0.02f, 0.02f);
-
Color frag(Color col, Texture tex, Vertex v)
{
return vec4(col.rgb, texel(tex, v.uv).a);
@@ -37,15 +36,37 @@ Color frag(Color col, Texture tex, Vertex v)
#END_FRAGMENT_SHADER
)";
- shader = Shader::createShader(program);
+ const char* canvas_shader = R"(
+#VERTEX_SHADER
+
+Vertex vert(Vertex v)
+{
+ return v;
+}
+
+#END_VERTEX_SHADER
+
+#FRAGMENT_SHADER
+
+Color frag(Color col, Texture tex, Vertex v)
+{
+ if(v.uv.x <= 0.002f || v.uv.x >= 0.998f || v.uv.y <= 0.005f || v.uv.y >= 0.995f)
+ return vec4(1, 1, 1, 1);
+ else
+ return texel(tex, v.uv);
+}
+
+#END_FRAGMENT_SHADER
+)";
+ shader = Shader::createShader(font_shader);
+ shader2 = Shader::createShader(canvas_shader);
Filesystem* fs = Filesystem::get();
fs->mount("../Debug");
Buffer buffer;
fs->read("font.ttf", &buffer);
data = FontData::createFontData((const unsigned char*)buffer.data, buffer.size);
- font = Font::createFont(data, 18);
- page = font->typeset(u8R"(
-平安時代中期の物語。紫式部著。ただし,そのすべてが紫式部の筆に成るのでは
+ font = Font::createFont(data, 15);
+ page = font->typeset(u8R"(平安時代中期の物語。紫式部著。ただし,そのすべてが紫式部の筆に成るのでは
ないとする説もある。 54帖。寛弘 (1004~12) 頃成立か。物語は3部に分けてみ
ることができる。第1部は,容貌,才能などすべてにすぐれた主人公光源氏が,多
啊哈噶科膜卡して広く迎えられている。貴族社会の苦悩を摘出したところに磁瓷得
@@ -61,7 +82,7 @@ Color frag(Color col, Texture tex, Vertex v)
》开始在日本东京电视台播出。2004年,漫画进而改编成电影。2006年,漩涡鸣人入选
美国《新闻周刊》日文版于10月18日发行的特集中选出的“全世界最受尊敬的100位日本
人”。[2]
-)", 20, 0);
+)", 17, 0);
delete data;
//canvas = Canvas::createCanvas(100, 100);
//page = font->typeset("こんにちは世界!", 120, 20);
@@ -69,7 +90,22 @@ Color frag(Color col, Texture tex, Vertex v)
fs->read("img.png", &buffer);
Bitmap* bitmap = Bitmap::createBitmap(buffer.data, buffer.size);
tex = Texture::createTexture(bitmap);
- canvas = Canvas::createCanvas(100, 100);
+ canvas = Canvas::createCanvas(page->width, page->height);
+
+ Canvas::bind(canvas);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColor4f(1, 1, 1, 1);
+ if (font != nullptr)
+ {
+ //font->print(u8"Hello,你好\n啊 world!", 10, 10);
+ //font->print(u8"Привет мир!", 10, 10 + 15 * 1);
+ shader->use();
+ font->print(page, 0, 0);
+ shader->unuse();
+ //font->print(u8"你好世界!", 10, 10 + 15*3);
+ //font->render(page);
+ }
+ Canvas::unbind();
}
void onEvent(jin::input::Event* e)
@@ -90,23 +126,13 @@ void onDraw()
glColor4f(1, 1, 1, 1);
//gl.pushColor(32, 32, 32, 255);
//rect(FILL, 0, 0, 500, 500);
- shader->use();
//circle(RenderMode::LINE, 50, 50, 30);
//tex->draw(0, 0, 1, 1, 0);
//tex->draw(20, 50, 1, 1, 0);
//shader->sendFloat("dt", dt);
- Canvas::bind(canvas);
- if (font != nullptr)
- {
- //font->print(u8"Hello,你好\n啊 world!", 10, 10);
- //font->print(u8"Привет мир!", 10, 10 + 15 * 1);
- font->print(page, 12, 10 + 15 * 2);
- //font->print(u8"你好世界!", 10, 10 + 15*3);
- //font->render(page);
- }
- Canvas::unbind();
- canvas->draw(0, 0, 1, 1, 0);
- shader->unuse();
+ shader2->use();
+ canvas->draw(20 * sin(dt), 10 * cos(dt), 1, 1, 0);
+ shader2->unuse();
}
int main(int argc, char* argv[])
diff --git a/test/06TextureFont/main.cpp b/test/06TextureFont/main.cpp
new file mode 100644
index 0000000..b28b04f
--- /dev/null
+++ b/test/06TextureFont/main.cpp
@@ -0,0 +1,3 @@
+
+
+