From ef2801e5a5dea45a2966e7fdd79bc6e9de205c30 Mon Sep 17 00:00:00 2001 From: chai Date: Sun, 14 Oct 2018 14:33:30 +0800 Subject: *texture font --- build/06TextureFont/06TextureFont.vcxproj | 134 +++++++++++ build/06TextureFont/06TextureFont.vcxproj.filters | 22 ++ build/06TextureFont/06TextureFont.vcxproj.user | 4 + build/Debug/font.png | Bin 0 -> 2780 bytes build/Debug/font2.png | Bin 0 -> 3407 bytes libjin/Filesystem/Filesystem.cpp | 2 + libjin/Game/Game.cpp | 1 + libjin/Graphics/Bitmap.h | 1 + libjin/Graphics/Font/Decoder.h | 15 +- libjin/Graphics/Font/Text.cpp | 13 + libjin/Graphics/Font/Text.h | 17 +- libjin/Graphics/Font/TextureFont.cpp | 281 ++++++++++++++++++++-- libjin/Graphics/Font/TextureFont.h | 12 +- libjin/Graphics/Graphics.h | 1 + libjin/Math/Vector2.hpp | 5 +- test/06TextureFont/main.cpp | 87 ++----- 16 files changed, 486 insertions(+), 109 deletions(-) create mode 100644 build/06TextureFont/06TextureFont.vcxproj create mode 100644 build/06TextureFont/06TextureFont.vcxproj.filters create mode 100644 build/06TextureFont/06TextureFont.vcxproj.user create mode 100644 build/Debug/font.png create mode 100644 build/Debug/font2.png diff --git a/build/06TextureFont/06TextureFont.vcxproj b/build/06TextureFont/06TextureFont.vcxproj new file mode 100644 index 0000000..2d1c462 --- /dev/null +++ b/build/06TextureFont/06TextureFont.vcxproj @@ -0,0 +1,134 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {9BE6EA25-E171-405D-86CA-AC13A7F387D1} + My06TextureFont + 10.0.17134.0 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + true + true + $(SolutionDir)..\libjin\;$(SolutionDir)\lib\SDL2-2.0.5\include\ + + + $(SolutionDir)\lib\SDL2-2.0.5\lib\x86\ + SDL2main.lib;SDL2.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies) + Console + + + + + Level3 + Disabled + true + true + + + + + Level3 + MaxSpeed + true + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + true + + + true + true + + + + + + + + {407e9199-d39c-4460-b218-0c29ab42483b} + + + + + + \ No newline at end of file diff --git a/build/06TextureFont/06TextureFont.vcxproj.filters b/build/06TextureFont/06TextureFont.vcxproj.filters new file mode 100644 index 0000000..c98198f --- /dev/null +++ b/build/06TextureFont/06TextureFont.vcxproj.filters @@ -0,0 +1,22 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 源文件 + + + \ No newline at end of file diff --git a/build/06TextureFont/06TextureFont.vcxproj.user b/build/06TextureFont/06TextureFont.vcxproj.user new file mode 100644 index 0000000..be25078 --- /dev/null +++ b/build/06TextureFont/06TextureFont.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/build/Debug/font.png b/build/Debug/font.png new file mode 100644 index 0000000..151b992 Binary files /dev/null and b/build/Debug/font.png differ diff --git a/build/Debug/font2.png b/build/Debug/font2.png new file mode 100644 index 0000000..11ab658 Binary files /dev/null and b/build/Debug/font2.png differ diff --git a/libjin/Filesystem/Filesystem.cpp b/libjin/Filesystem/Filesystem.cpp index 3f91274..c3d271c 100644 --- a/libjin/Filesystem/Filesystem.cpp +++ b/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/libjin/Game/Game.cpp b/libjin/Game/Game.cpp index 6dc75ce..f4e672d 100644 --- a/libjin/Game/Game.cpp +++ b/libjin/Game/Game.cpp @@ -46,6 +46,7 @@ namespace core if (_onDraw != nullptr) _onDraw(); wnd->swapBuffers(); + sleep(1); } quitloop:; } diff --git a/libjin/Graphics/Bitmap.h b/libjin/Graphics/Bitmap.h index 85b9044..553d999 100644 --- a/libjin/Graphics/Bitmap.h +++ b/libjin/Graphics/Bitmap.h @@ -33,6 +33,7 @@ namespace graphics /* get width and height */ inline int getWidth() const { return width; } inline int getHeight() const { return height; } + inline math::Vector2 getSize() const { return math::Vector2(width, height); } protected: Bitmap(); diff --git a/libjin/Graphics/Font/Decoder.h b/libjin/Graphics/Font/Decoder.h index 83570e9..5333bd3 100644 --- a/libjin/Graphics/Font/Decoder.h +++ b/libjin/Graphics/Font/Decoder.h @@ -3,24 +3,13 @@ #include +#include "Text.h" + namespace jin { namespace graphics { - typedef unsigned int Codepoint; - - typedef std::vector Content; - - enum Encode - { - UCS16, // unicode 16bits - UCS32, // unicode 32bits - UTF8, // utf-8 - UTF16, // utf-16 - ASCII, // ASCII - }; - class Decoder { public: diff --git a/libjin/Graphics/Font/Text.cpp b/libjin/Graphics/Font/Text.cpp index b3ba473..6c569cd 100644 --- a/libjin/Graphics/Font/Text.cpp +++ b/libjin/Graphics/Font/Text.cpp @@ -1,4 +1,7 @@ +#include + #include "Text.h" +#include "Decoder.h" namespace jin { @@ -35,6 +38,7 @@ namespace graphics Text::Iterator::~Iterator() { + delete decoder; } Codepoint Text::Iterator::get() @@ -108,6 +112,15 @@ namespace graphics // 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); diff --git a/libjin/Graphics/Font/Text.h b/libjin/Graphics/Font/Text.h index d092d41..ac2d239 100644 --- a/libjin/Graphics/Font/Text.h +++ b/libjin/Graphics/Font/Text.h @@ -1,19 +1,34 @@ #ifndef __LIBJIN_TEXT_H #define __LIBJIN_TEXT_H -#include "Decoder.h" +#include namespace jin { namespace graphics { + typedef unsigned int Codepoint; + + typedef std::vector Content; + class Text; + class Decoder; + + enum Encode + { + UCS16, // unicode 16bits + UCS32, // unicode 32bits + 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(); diff --git a/libjin/Graphics/Font/TextureFont.cpp b/libjin/Graphics/Font/TextureFont.cpp index 89600c7..4dde236 100644 --- a/libjin/Graphics/Font/TextureFont.cpp +++ b/libjin/Graphics/Font/TextureFont.cpp @@ -1,3 +1,7 @@ +#include + +#include "../../Math/Vector2.hpp" +#include "../Shader.h" #include "TextureFont.h" namespace jin @@ -5,60 +9,291 @@ namespace jin namespace graphics { - /* create texture font from tilemap */ - TextureFont * TextureFont::createTextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh) - { - TextureFont* tf = new TextureFont(bitmap, codepoints, cellw, cellh); - return tf; - } + using namespace std; + using namespace math; - /* create texture font from seperated glyphs */ - 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 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() { } - Page* TextureFont::typeset(const Content& text, int lineheight, int spacing) - { + const TextureFont::TextureGlyph* TextureFont::findGlyph(Codepoint codepoint) const + { + auto it = glyphs.find(codepoint); + if (it != glyphs.end()) + { + return &it->second; + } + else + return nullptr; + } - return nullptr; - } + Page* TextureFont::typeset(const Content& text, int lineheight, int spacing) + { + Page* page = new Page(); + page->font = this; + vector& glyphinfolist = page->glyphinfolist; + vector& glyphvertices = page->glyphvertices; + int texture = -1; + const TextureGlyph* glyph = nullptr; + GlyphVertex vertex; + Vector2 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 nullptr; + return typeset(*text, lineheight, spacing); } void TextureFont::print(const Page* page, int x, int y) { - + Shader* shader = Shader::getCurrentShader(); + const vector& glyphinfolist = page->glyphinfolist; + const vector& 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 linehgiht, int spacing) + 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) { - int l, r, t, b; - + TextureGlyph glyph; + Vector2 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(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(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(codepoints[i], glyph)); + if (codepoints[i] == 't') + { + int a = 10; + } + ++i; + newc = false; + } + } + } } } diff --git a/libjin/Graphics/Font/TextureFont.h b/libjin/Graphics/Font/TextureFont.h index 243c9d5..0d0d091 100644 --- a/libjin/Graphics/Font/TextureFont.h +++ b/libjin/Graphics/Font/TextureFont.h @@ -37,11 +37,21 @@ namespace graphics void print(const Text& text, int x, int y, int lineheight, int spacing = 0)override; private: - struct TextureGlyph { unsigned short x, y, w, h;}; + 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 glyphs; }; diff --git a/libjin/Graphics/Graphics.h b/libjin/Graphics/Graphics.h index bca2f6f..54889f9 100644 --- a/libjin/Graphics/Graphics.h +++ b/libjin/Graphics/Graphics.h @@ -13,6 +13,7 @@ #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/libjin/Math/Vector2.hpp b/libjin/Math/Vector2.hpp index bee22f3..ddb8221 100644 --- a/libjin/Math/Vector2.hpp +++ b/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/test/06TextureFont/main.cpp b/test/06TextureFont/main.cpp index 9551604..1512ad6 100644 --- a/test/06TextureFont/main.cpp +++ b/test/06TextureFont/main.cpp @@ -1,4 +1,4 @@ -#include +#include #include "jin.h" using namespace jin::core; @@ -6,13 +6,16 @@ using namespace jin::graphics; using namespace jin::input; using namespace jin::audio; using namespace jin::filesystem; -Font* font = nullptr; -Canvas* canvas; -TTFData* data = nullptr; Shader* shader = nullptr; -Shader* shader2 = nullptr; -Page* page = nullptr; -Texture* tex = nullptr; +TextureFont* font = nullptr; +Text text = Text( +Encode::UTF8, +u8R"( +this is a test +you know what i mean +texture font test ^_^ +)" +); float dt; void onLoad() @@ -31,68 +34,19 @@ Vertex vert(Vertex v) Color frag(Color col, Texture tex, Vertex v) { - return vec4(col.rgb, texel(tex, v.uv).a); -} - -#END_FRAGMENT_SHADER - )"; - 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); + return col * 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 = TTFData::createTTFData((const unsigned char*)buffer.data, buffer.size); - font = TTF::createTTF(data, 15); - const char* str = u8R"(Դ爐󤸤Τ)"; - int l = strlen(str); - Text text = Text(Encode::UTF8, str, strlen(str)); - page = font->typeset(text, 15, 0); - delete data; - //canvas = Canvas::createCanvas(100, 100); - //page = font->typeset("ˤ!", 120, 20); - buffer.clear(); - fs->read("img.png", &buffer); + fs->read("font2.png", &buffer); Bitmap* bitmap = Bitmap::createBitmap(buffer.data, buffer.size); - tex = Texture::createTexture(bitmap); - canvas = Canvas::createCanvas(page->size.w, page->size.h); - - 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(); + const char* charset = u8R"( !"#$£€%&'()*+,-./0123456789;:<=>?`'^@abcdefghijklmnopqrstuvwxyz|~[\]_)"; + font = TextureFont::createTextureFont(bitmap, Text(Encode::UTF8, charset, strlen(charset)), Color(255, 0, 0, 255), 16); } void onEvent(jin::input::Event* e) @@ -109,17 +63,12 @@ void onUpdate(int ms) void onDraw() { + gl.setClearColor(255, 255, 255, 255); glClear(GL_COLOR_BUFFER_BIT); glColor4f(1, 1, 1, 1); - //gl.pushColor(32, 32, 32, 255); - //rect(FILL, 0, 0, 500, 500); - //circle(RenderMode::LINE, 50, 50, 30); - //tex->draw(0, 0, 1, 1, 0); - //tex->draw(20, 50, 1, 1, 0); - //shader->sendFloat("dt", dt); - shader2->use(); - canvas->draw(20 * sin(dt), 10 * cos(dt), 1, 1, 0); - shader2->unuse(); + shader->use(); + font->print(text, 10, 10, 16); + shader->unuse(); } int main(int argc, char* argv[]) -- cgit v1.1-26-g67d0