diff options
Diffstat (limited to 'src/libjin/graphics/fonts')
-rw-r--r-- | src/libjin/graphics/fonts/decoder.cpp | 162 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/decoder.h | 170 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/font.h | 204 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/page.h | 84 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/text.cpp | 298 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/text.h | 324 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/texture_font.cpp | 548 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/texture_font.h | 222 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/ttf.cpp | 858 | ||||
-rw-r--r-- | src/libjin/graphics/fonts/ttf.h | 520 |
10 files changed, 1695 insertions, 1695 deletions
diff --git a/src/libjin/graphics/fonts/decoder.cpp b/src/libjin/graphics/fonts/decoder.cpp index 5c74258..2b6fb66 100644 --- a/src/libjin/graphics/fonts/decoder.cpp +++ b/src/libjin/graphics/fonts/decoder.cpp @@ -4,93 +4,93 @@ namespace JinEngine { - namespace Graphics - { - namespace Fonts - { + namespace Graphics + { + namespace Fonts + { - /* utf8 byte string to unicode codepoint */ - static const char *utf8toCodepoint(const char *p, unsigned *res) { - return nullptr; + /* utf8 byte string to unicode codepoint */ + static const char *utf8toCodepoint(const char *p, unsigned *res) { + return nullptr; - } + } - ///////////////////////////////////////////////////////////////////////////// - // decoders - ///////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////// + // 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::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* 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* 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; - } + const void* Ascii::next(const void* data) const + { + const char* p = (char*)data; + return p + 1; + } - } // namespace Fonts - } // namespace Graphics + } // namespace Fonts + } // namespace Graphics } // namespace JinEngine
\ No newline at end of file diff --git a/src/libjin/graphics/fonts/decoder.h b/src/libjin/graphics/fonts/decoder.h index 8ff7bd7..e5e7bda 100644 --- a/src/libjin/graphics/fonts/decoder.h +++ b/src/libjin/graphics/fonts/decoder.h @@ -9,91 +9,91 @@ namespace JinEngine { - namespace Graphics - { - namespace Fonts - { - - /// - /// Text decoder. - /// - class Decoder : public Object - { - public: - - /// - /// Decode a code unit. - /// - /// @param data Code units. - /// @param codepoint Value of code point. - /// @return Next code unit location. - /// - virtual const void* decode(const void* data, Codepoint* codepoint) const = 0; - - /// - /// Get next code unit location. - /// - /// @param data Code units. - /// @return Next code unit location. - /// - virtual const void* next(const void* data) const = 0; - - }; - - /// - /// Utf-8 decoder. - /// - class Utf8 : public Decoder - { - public: - - /// - /// Decode a code unit. - /// - /// @param data Code units. - /// @param codepoint Value of code point. - /// @return Next code unit location. - /// - const void* decode(const void* data, Codepoint* codepoint) const override; - - /// - /// Get next code unit location. - /// - /// @param data Code units. - /// @return Next code unit location. - /// - const void* next(const void* data) const override; - - }; - - /// - /// Ascii decoder. - /// - class Ascii : public Decoder - { - public: - - /// - /// Decode a code unit. - /// - /// @param data Code units. - /// @param codepoint Value of code point. - /// @return Next code unit location. - /// - const void* decode(const void* data, Codepoint* codepoint) const override; - - /// - /// Get next code unit location. - /// - /// @param data Code units. - /// @return Next code unit location. - /// - const void* next(const void* data) const override; - - }; - - } // namespace Fonts - } // namespace Graphics + namespace Graphics + { + namespace Fonts + { + + /// + /// Text decoder. + /// + class Decoder : public Object + { + public: + + /// + /// Decode a code unit. + /// + /// @param data Code units. + /// @param codepoint Value of code point. + /// @return Next code unit location. + /// + virtual const void* decode(const void* data, Codepoint* codepoint) const = 0; + + /// + /// Get next code unit location. + /// + /// @param data Code units. + /// @return Next code unit location. + /// + virtual const void* next(const void* data) const = 0; + + }; + + /// + /// Utf-8 decoder. + /// + class Utf8 : public Decoder + { + public: + + /// + /// Decode a code unit. + /// + /// @param data Code units. + /// @param codepoint Value of code point. + /// @return Next code unit location. + /// + const void* decode(const void* data, Codepoint* codepoint) const override; + + /// + /// Get next code unit location. + /// + /// @param data Code units. + /// @return Next code unit location. + /// + const void* next(const void* data) const override; + + }; + + /// + /// Ascii decoder. + /// + class Ascii : public Decoder + { + public: + + /// + /// Decode a code unit. + /// + /// @param data Code units. + /// @param codepoint Value of code point. + /// @return Next code unit location. + /// + const void* decode(const void* data, Codepoint* codepoint) const override; + + /// + /// Get next code unit location. + /// + /// @param data Code units. + /// @return Next code unit location. + /// + const void* next(const void* data) const override; + + }; + + } // namespace Fonts + } // namespace Graphics } // namespace JinEngine #endif
\ No newline at end of file diff --git a/src/libjin/graphics/fonts/font.h b/src/libjin/graphics/fonts/font.h index 166cd6b..b206a2d 100644 --- a/src/libjin/graphics/fonts/font.h +++ b/src/libjin/graphics/fonts/font.h @@ -9,108 +9,108 @@ namespace JinEngine { - namespace Graphics - { - namespace Fonts - { - - struct Page; - - // - // Font - // |- TTF - // |- TextureFont - // - - /// - /// Base Font class. - /// - class Font : public Object, public Renderable - { - public: - /// - /// Font constructor. - /// - Font(unsigned fontsize) - : mFontSize(fontsize) - { - ++gl.getStats().fonts; - } - - /// - /// Font destructor. - /// - virtual ~Font() - { - --gl.getStats().fonts; - }; - - /// - /// Create page with given text. - /// - /// @param text Text to be typesetted. - /// @param lineheight Line height of text. - /// @param spacing Spacing between characters. 0 by default. - /// @return Page if created successfully, otherwise return null. - /// - virtual Page* typeset(const Text& text, int lineheight, int spacing = 0) = 0; - - /// - /// Create page with given unicode codepoints. - /// - /// @param content Unicode codepoints to be typesetted. - /// @param lineheight Line height of text. - /// @param spacing Spacing between characters. 0 by default. - /// @return Page if created successfully, otherwise return null. - /// - virtual Page* typeset(const Content& content, int lineheight, int spacing = 0) = 0; - - /// - /// Render page to given position. - /// - /// @param page Page to be rendered. - /// @param x X value of the position. - /// @param y Y value of the position. - /// - virtual void render(const Page* page, int x, int y) = 0; - - /// - /// Render unicode codepoints to given position. - /// - /// @param content Unicode codepoints to be typesetted. - /// @param x X value of the position. - /// @param y Y value of the position. - /// @param lineheight Line height of the content. - /// @param spacing Spacing between characters. - /// - virtual void render(const Content& content, int x, int y, int lineheight, int spacing = 0) = 0; - - /// - /// Render text to given position. - /// - /// @param text Text to be rendered. - /// @param x X value of the position. - /// @param y Y value of the position. - /// @param lineheight Line height of the text. - /// @param spacing Spacing between characters. - /// - virtual void render(const Text& text, int x, int y, int lineheight, int spacing = 0) = 0; - - /// - /// Get font size. - /// - /// @return Font size. - /// - inline unsigned getFontSize() { return mFontSize; }; - - protected: - - unsigned mFontSize; - - }; - - } // namespace Fonts - } // namespace Graphics + namespace Graphics + { + namespace Fonts + { + + struct Page; + + // + // Font + // |- TTF + // |- TextureFont + // + + /// + /// Base Font class. + /// + class Font : public Object, public Renderable + { + public: + /// + /// Font constructor. + /// + Font(unsigned fontsize) + : mFontSize(fontsize) + { + ++gl.getStats().fonts; + } + + /// + /// Font destructor. + /// + virtual ~Font() + { + --gl.getStats().fonts; + }; + + /// + /// Create page with given text. + /// + /// @param text Text to be typesetted. + /// @param lineheight Line height of text. + /// @param spacing Spacing between characters. 0 by default. + /// @return Page if created successfully, otherwise return null. + /// + virtual Page* typeset(const Text& text, int lineheight, int spacing = 0) = 0; + + /// + /// Create page with given unicode codepoints. + /// + /// @param content Unicode codepoints to be typesetted. + /// @param lineheight Line height of text. + /// @param spacing Spacing between characters. 0 by default. + /// @return Page if created successfully, otherwise return null. + /// + virtual Page* typeset(const Content& content, int lineheight, int spacing = 0) = 0; + + /// + /// Render page to given position. + /// + /// @param page Page to be rendered. + /// @param x X value of the position. + /// @param y Y value of the position. + /// + virtual void render(const Page* page, int x, int y) = 0; + + /// + /// Render unicode codepoints to given position. + /// + /// @param content Unicode codepoints to be typesetted. + /// @param x X value of the position. + /// @param y Y value of the position. + /// @param lineheight Line height of the content. + /// @param spacing Spacing between characters. + /// + virtual void render(const Content& content, int x, int y, int lineheight, int spacing = 0) = 0; + + /// + /// Render text to given position. + /// + /// @param text Text to be rendered. + /// @param x X value of the position. + /// @param y Y value of the position. + /// @param lineheight Line height of the text. + /// @param spacing Spacing between characters. + /// + virtual void render(const Text& text, int x, int y, int lineheight, int spacing = 0) = 0; + + /// + /// Get font size. + /// + /// @return Font size. + /// + inline unsigned getFontSize() { return mFontSize; }; + + protected: + + unsigned mFontSize; + + }; + + } // namespace Fonts + } // namespace Graphics } // namespace JinEngine #endif // __JE_FONT_H__ diff --git a/src/libjin/graphics/fonts/page.h b/src/libjin/graphics/fonts/page.h index 75f1840..0a9b5e2 100644 --- a/src/libjin/graphics/fonts/page.h +++ b/src/libjin/graphics/fonts/page.h @@ -7,48 +7,48 @@ namespace JinEngine { - namespace Graphics - { - namespace Fonts - { - - class Font; - - /// - /// Glyphs data to be rendered. - /// - struct GlyphVertex - { - int x, y; ///< screen coordinates - float u, v; ///< normalized texture uv - }; - - /// - /// Glyphs info for reducing draw call. - /// - struct GlyphArrayDrawInfo - { - GLuint texture; ///< atlas - unsigned int start; ///< glyph vertex indecies - unsigned int count; ///< glyph vertex count - }; - - /// - /// Page to be rendered. - /// - /// A page is a pre-rendered text struct for reducing draw call. Each page - /// keeps a font pointer which should not be changed. - /// - struct Page : public Object - { - Font* font; - std::vector<GlyphArrayDrawInfo> glyphinfolist; - std::vector<GlyphVertex> glyphvertices; - Math::Vector2<int> size; - }; - - } // namespace Fonts - } // namespace Graphics + namespace Graphics + { + namespace Fonts + { + + class Font; + + /// + /// Glyphs data to be rendered. + /// + struct GlyphVertex + { + int x, y; ///< screen coordinates + float u, v; ///< normalized texture uv + }; + + /// + /// Glyphs info for reducing draw call. + /// + struct GlyphArrayDrawInfo + { + GLuint texture; ///< atlas + unsigned int start; ///< glyph vertex indecies + unsigned int count; ///< glyph vertex count + }; + + /// + /// Page to be rendered. + /// + /// A page is a pre-rendered text struct for reducing draw call. Each page + /// keeps a font pointer which should not be changed. + /// + struct Page : public Object + { + Font* font; + std::vector<GlyphArrayDrawInfo> glyphinfolist; + std::vector<GlyphVertex> glyphvertices; + Math::Vector2<int> size; + }; + + } // namespace Fonts + } // namespace Graphics } // namespace JinEngine #endif // __JE_PAGE_H__ diff --git a/src/libjin/graphics/fonts/text.cpp b/src/libjin/graphics/fonts/text.cpp index 9684b81..311c8c8 100644 --- a/src/libjin/graphics/fonts/text.cpp +++ b/src/libjin/graphics/fonts/text.cpp @@ -5,153 +5,153 @@ namespace JinEngine { - namespace Graphics - { - namespace Fonts - { - - ///////////////////////////////////////////////////////////////////////////// - // 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::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::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) - { - unsigned length = strlen((const char*)data); - Iterator end = Iterator(encode, data, length); - end.toEnd(); - Iterator it = Iterator(encode, data, length); - for (; it != end; ++it) - { - content.push_back(*it); - } - } - - Text::Text(Encode encode, const void* data, unsigned length) - { - Iterator end = Iterator(encode, data, length); - end.toEnd(); - Iterator it = Iterator(encode, data, length); - for (; it != end; ++it) - { - content.push_back(*it); - } - } - - Text::~Text() - { - } - - const Content& Text::getContent() const - { - return content; - } - - const Content& Text::operator*() const - { - return content; - } - - } // namespace Fonts - } // namespace Graphics + namespace Graphics + { + namespace Fonts + { + + ///////////////////////////////////////////////////////////////////////////// + // 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::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::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) + { + unsigned length = strlen((const char*)data); + Iterator end = Iterator(encode, data, length); + end.toEnd(); + Iterator it = Iterator(encode, data, length); + for (; it != end; ++it) + { + content.push_back(*it); + } + } + + Text::Text(Encode encode, const void* data, unsigned length) + { + Iterator end = Iterator(encode, data, length); + end.toEnd(); + Iterator it = Iterator(encode, data, length); + for (; it != end; ++it) + { + content.push_back(*it); + } + } + + Text::~Text() + { + } + + const Content& Text::getContent() const + { + return content; + } + + const Content& Text::operator*() const + { + return content; + } + + } // namespace Fonts + } // namespace Graphics } // namespace JinEngine
\ No newline at end of file diff --git a/src/libjin/graphics/fonts/text.h b/src/libjin/graphics/fonts/text.h index c3bb8db..fe02d36 100644 --- a/src/libjin/graphics/fonts/text.h +++ b/src/libjin/graphics/fonts/text.h @@ -7,168 +7,168 @@ namespace JinEngine { - namespace Graphics - { - namespace Fonts - { - - typedef unsigned int Codepoint; - - typedef std::vector<Codepoint> Content; - - class Text; - - class Decoder; - - /// - /// Supported text encoding. - /// - enum Encode - { - UTF8, ///< utf-8 - ASCII, ///< ASCII - }; - - /// - /// Decoded text. Saved as unicode codepoints. - /// - class Text : public Object - { - 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 *(); - - /// - /// - /// - Iterator& operator ++(); - - /// - /// - /// - 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; - - }; - - } - } // namespace Graphics + namespace Graphics + { + namespace Fonts + { + + typedef unsigned int Codepoint; + + typedef std::vector<Codepoint> Content; + + class Text; + + class Decoder; + + /// + /// Supported text encoding. + /// + enum Encode + { + UTF8, ///< utf-8 + ASCII, ///< ASCII + }; + + /// + /// Decoded text. Saved as unicode codepoints. + /// + class Text : public Object + { + 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 *(); + + /// + /// + /// + Iterator& operator ++(); + + /// + /// + /// + 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; + + }; + + } + } // namespace Graphics } // namespace JinEngine #endif
\ No newline at end of file diff --git a/src/libjin/graphics/fonts/texture_font.cpp b/src/libjin/graphics/fonts/texture_font.cpp index 31e5293..33e3bf1 100644 --- a/src/libjin/graphics/fonts/texture_font.cpp +++ b/src/libjin/graphics/fonts/texture_font.cpp @@ -12,298 +12,298 @@ using namespace JinEngine::Graphics::Shaders; namespace JinEngine { - namespace Graphics - { - namespace Fonts - { + namespace Graphics + { + namespace Fonts + { - TextureFont::TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh) - : Graphic(bitmap) - , Font(cellh) - { - 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, int cellw, int cellh) + : Graphic(bitmap) + , Font(cellh) + { + 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) - : Graphic(bitmap) - , Font(cellh) - { - 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; - } - } - } - } + TextureFont::TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh) + : Graphic(bitmap) + , Font(cellh) + { + 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; + } + } + } + } - TextureFont::TextureFont(const Bitmap* bitmap, const Text& text, Color mask, int cellh) - : TextureFont(bitmap, *text, mask, cellh) - { - } + TextureFont::TextureFont(const Bitmap* bitmap, const Text& text, Color mask, int cellh) + : TextureFont(bitmap, *text, mask, cellh) + { + } - TextureFont::TextureFont(const Bitmap* bitmap, const Text& text, int cellw, int cellh) - : TextureFont(bitmap, *text, cellw, cellh) - { - } + TextureFont::TextureFont(const Bitmap* bitmap, const Text& text, int cellw, int cellh) + : TextureFont(bitmap, *text, cellw, cellh) + { + } - TextureFont::~TextureFont() - { - } + 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; - } + 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; + 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);\ + vertex.x = _x; vertex.y = _y;\ + vertex.u = _u; vertex.v = _v;\ + glyphvertices.push_back(vertex);\ - for (Codepoint c : text) - { - // return - if (c == 0x0D) continue; - // newline - if (c == 0x0A) - { - p.y() += lineheight; - p.x() = 0; - continue; - } - if (c == 0x09) - { - // tab = 4*space - unsigned cw = getCharWidth(0x20); - p.x() += cw * 4; - continue; - } - glyph = findGlyph(c); - if (glyph == nullptr) continue; - if (texture != getGLTexture()) - { - texture = getGLTexture(); - GlyphArrayDrawInfo info; - info.start = i; - info.count = 0; - info.texture = texture; - glyphinfolist.push_back(info); - } - glyphinfolist[glyphinfolist.size() - 1].count += 4; - // normalized - float w = getWidth(), h = getHeight(); - float nx = glyph->x / w, ny = glyph->y / h; - float nw = glyph->w / w, nh = glyph->h / 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; - } + for (Codepoint c : text) + { + // return + if (c == 0x0D) continue; + // newline + if (c == 0x0A) + { + p.y() += lineheight; + p.x() = 0; + continue; + } + if (c == 0x09) + { + // tab = 4*space + unsigned cw = getCharWidth(0x20); + p.x() += cw * 4; + continue; + } + glyph = findGlyph(c); + if (glyph == nullptr) continue; + if (texture != getGLTexture()) + { + texture = getGLTexture(); + GlyphArrayDrawInfo info; + info.start = i; + info.count = 0; + info.texture = texture; + glyphinfolist.push_back(info); + } + glyphinfolist[glyphinfolist.size() - 1].count += 4; + // normalized + float w = getWidth(), h = getHeight(); + float nx = glyph->x / w, ny = glyph->y / h; + float nw = glyph->w / w, nh = glyph->h / 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::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::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; - } - if (c == 0x09) - { - // tab = 4*space - unsigned cw = getCharWidth(0x20); - tmp += cw * 4; - if (tmp > res) res = tmp; - continue; - } - tmp += getCharWidth(c) + spacing; - if (tmp > res) res = tmp; - } - return res; - } + 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; + } + if (c == 0x09) + { + // tab = 4*space + unsigned cw = getCharWidth(0x20); + tmp += cw * 4; + if (tmp > res) res = tmp; + 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; - } + 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; - } - } + 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); - } + Page* TextureFont::typeset(const Text& text, int lineheight, int spacing) + { + return typeset(*text, lineheight, spacing); + } - void TextureFont::render(const Page* page, int x, int y) - { - Shader* shader = gl.getShader(); - const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist; - const vector<GlyphVertex>& glyphvertices = page->glyphvertices; - Matrix modelMatrix = gl.getModelViewMatrix(x, y, 1, 1, 0, 0, 0); - shader->begin() - .sendMatrix4(SHADER_MODELVIEW_MATRIX, &modelMatrix) - .sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.getProjectionMatrix()); - for (int i = 0; i < glyphinfolist.size(); ++i) - { - const GlyphArrayDrawInfo& info = glyphinfolist[i]; - shader->uploadVertices(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x) - .uploadUV(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u); - gl.bindTexture2D(info.texture); - gl.drawArrays(GL_QUADS, 0, info.count); - } - shader->end(); - } + void TextureFont::render(const Page* page, int x, int y) + { + Shader* shader = gl.getShader(); + const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist; + const vector<GlyphVertex>& glyphvertices = page->glyphvertices; + Matrix modelMatrix = gl.getModelViewMatrix(x, y, 1, 1, 0, 0, 0); + shader->begin() + .sendMatrix4(SHADER_MODELVIEW_MATRIX, &modelMatrix) + .sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.getProjectionMatrix()); + for (int i = 0; i < glyphinfolist.size(); ++i) + { + const GlyphArrayDrawInfo& info = glyphinfolist[i]; + shader->uploadVertices(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x) + .uploadUV(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u); + gl.bindTexture2D(info.texture); + gl.drawArrays(GL_QUADS, 0, info.count); + } + shader->end(); + } - void TextureFont::render(const Content& text, int x, int y, int lineheight, int spacing) - { - Page* page = typeset(text, lineheight, spacing); - render(page, x, y); - delete page; - } + void TextureFont::render(const Content& text, int x, int y, int lineheight, int spacing) + { + Page* page = typeset(text, lineheight, spacing); + render(page, x, y); + delete page; + } - void TextureFont::render(const Text& text, int x, int y, int lineheight, int spacing) - { - Page* page = typeset(text, lineheight, spacing); - render(page, x, y); - delete page; - } + void TextureFont::render(const Text& text, int x, int y, int lineheight, int spacing) + { + Page* page = typeset(text, lineheight, spacing); + render(page, x, y); + delete page; + } - } - } + } + } }
\ No newline at end of file diff --git a/src/libjin/graphics/fonts/texture_font.h b/src/libjin/graphics/fonts/texture_font.h index 1d7f0d2..510badb 100644 --- a/src/libjin/graphics/fonts/texture_font.h +++ b/src/libjin/graphics/fonts/texture_font.h @@ -15,117 +15,117 @@ namespace JinEngine { - namespace Graphics - { - namespace Fonts - { - - /// - /// - /// - class TextureFont : public Font, public Graphic, public Object - { - public: - /// - /// - /// - TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh); - - /// - /// - /// - TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh); - - /// - /// - /// - TextureFont(const Bitmap* bitmap, const Text& text, Color mask, int cellh); - - /// - /// - /// - TextureFont(const Bitmap* bitmap, const Text& text, int cellw, 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 render(const Page* page, int x, int y) override; - - /// - /// - /// - void render(const Content& text, int x, int y, int linehgiht, int spacing = 0) override; - - /// - /// - /// - void render(const Text& text, int x, int y, int lineheight, int spacing = 0)override; - - private: - - /// - /// - /// - struct TextureGlyph - { - float x, y, w, h; - }; - - /// - /// - /// - 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; - - }; - - } // namespace Fonts - } // namespace Graphics + namespace Graphics + { + namespace Fonts + { + + /// + /// + /// + class TextureFont : public Font, public Graphic, public Object + { + public: + /// + /// + /// + TextureFont(const Bitmap* bitmap, const Content& codepoints, int cellw, int cellh); + + /// + /// + /// + TextureFont(const Bitmap* bitmap, const Content& codepoints, Color mask, int cellh); + + /// + /// + /// + TextureFont(const Bitmap* bitmap, const Text& text, Color mask, int cellh); + + /// + /// + /// + TextureFont(const Bitmap* bitmap, const Text& text, int cellw, 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 render(const Page* page, int x, int y) override; + + /// + /// + /// + void render(const Content& text, int x, int y, int linehgiht, int spacing = 0) override; + + /// + /// + /// + void render(const Text& text, int x, int y, int lineheight, int spacing = 0)override; + + private: + + /// + /// + /// + struct TextureGlyph + { + float x, y, w, h; + }; + + /// + /// + /// + 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; + + }; + + } // namespace Fonts + } // namespace Graphics } // namespace JinEngine #endif
\ No newline at end of file diff --git a/src/libjin/graphics/fonts/ttf.cpp b/src/libjin/graphics/fonts/ttf.cpp index 1357810..b540fda 100644 --- a/src/libjin/graphics/fonts/ttf.cpp +++ b/src/libjin/graphics/fonts/ttf.cpp @@ -19,438 +19,438 @@ using namespace JinEngine::Graphics::Shaders; namespace JinEngine { - namespace Graphics - { - namespace Fonts - { - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - // TTFData - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - 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); - } - - TTF* TTFData::createTTF(unsigned fontSize) - { - TTF* ttf; - try - { - ttf = new TTF(this, fontSize); - } - catch (...) - { - return nullptr; - } - return ttf; - } - - /* - * (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 - ////////////////////////////////////////////////////////////////////////////////////////////////////// + namespace Graphics + { + namespace Fonts + { + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + // TTFData + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + 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); + } + + TTF* TTFData::createTTF(unsigned fontSize) + { + TTF* ttf; + try + { + ttf = new TTF(this, fontSize); + } + catch (...) + { + return nullptr; + } + return ttf; + } + + /* + * (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/built-in/font.shader.h" - using namespace std; - using namespace JinEngine::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 }; - - /* little endian unicode */ - static const char* unicodeLittleEndian(const char* p, unsigned* res) - { - } - - //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) - : Font(fontSize) - , cursor(0, 0) - , ttf(f) - { - ttf->pushTTFsize(fontSize); - 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.bindTexture2D(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); - - return 0; - } - atlases.push_back(t); - - return t; - } - - void TTF::render(const Content& t, int x, int y, int lineheight, int spacing) - { - Page* page = typeset(t, lineheight, spacing); - render(page, x, y); - delete page; - } - - 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; - - #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) - - for (Codepoint c : text) - { - if (c == 0x0D) - continue; - if (c == 0x0A) - { - /* new line */ - p.y() += lineheight; - p.x() = 0; - continue; - } - if (c == 0x09) - { - // tab = 4*space - unsigned cw = getCharWidth(0x20); - p.x() += cw * 4; - 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::render(const Page* page, int x, int y) - { - Shader* shader = gl.getShader(); - const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist; - const vector<GlyphVertex>& glyphvertices = page->glyphvertices; - Matrix modelMatrix = gl.getModelViewMatrix(x, y, 1, 1, 0, 0, 0); - shader->begin() - .sendMatrix4(SHADER_MODELVIEW_MATRIX, &modelMatrix) - .sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.getProjectionMatrix()); - for (int i = 0; i < glyphinfolist.size(); ++i) - { - const GlyphArrayDrawInfo& info = glyphinfolist[i]; - shader->uploadVertices(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x) - .uploadUV(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u); - gl.bindTexture2D(info.texture); - gl.drawArrays(GL_QUADS, 0, info.count); - - } - shader->end(); - } - - void TTF::render(const Text& text, int x, int y, int lineheight, int spacing /* = 0 */) - { - render(*text, x, y, lineheight, spacing); - } - - int TTF::getCharWidth(int c) - { - int adw, lsb; - ttf->pushTTFsize(mFontSize); - 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(mFontSize); - 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(mFontSize); - 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(mFontSize); - *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(mFontSize); - GLuint atlas = atlases.back(); - const Color* bitmap = ttf->getCodepointBitmap(character, &w, &h, &xoff, &yoff); - int adw, lsb; - { - /* bake glyph */ - 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.bindTexture2D(atlas); - gl.texSubImage(cursor.x() + xoff, cursor.y() + yoff + baseline, w, h, GL_RGBA, GL_UNSIGNED_BYTE, bitmap); - gl.bindTexture2D(); - 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); - } - - } // namespace Fonts - } // namespace Graphics + using namespace std; + using namespace JinEngine::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 }; + + /* little endian unicode */ + static const char* unicodeLittleEndian(const char* p, unsigned* res) + { + } + + //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) + : Font(fontSize) + , cursor(0, 0) + , ttf(f) + { + ttf->pushTTFsize(fontSize); + 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.bindTexture2D(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); + + return 0; + } + atlases.push_back(t); + + return t; + } + + void TTF::render(const Content& t, int x, int y, int lineheight, int spacing) + { + Page* page = typeset(t, lineheight, spacing); + render(page, x, y); + delete page; + } + + 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; + + #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) + + for (Codepoint c : text) + { + if (c == 0x0D) + continue; + if (c == 0x0A) + { + /* new line */ + p.y() += lineheight; + p.x() = 0; + continue; + } + if (c == 0x09) + { + // tab = 4*space + unsigned cw = getCharWidth(0x20); + p.x() += cw * 4; + 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::render(const Page* page, int x, int y) + { + Shader* shader = gl.getShader(); + const vector<GlyphArrayDrawInfo>& glyphinfolist = page->glyphinfolist; + const vector<GlyphVertex>& glyphvertices = page->glyphvertices; + Matrix modelMatrix = gl.getModelViewMatrix(x, y, 1, 1, 0, 0, 0); + shader->begin() + .sendMatrix4(SHADER_MODELVIEW_MATRIX, &modelMatrix) + .sendMatrix4(SHADER_PROJECTION_MATRIX, &gl.getProjectionMatrix()); + for (int i = 0; i < glyphinfolist.size(); ++i) + { + const GlyphArrayDrawInfo& info = glyphinfolist[i]; + shader->uploadVertices(2, GL_INT, sizeof(GlyphVertex), &glyphvertices[info.start].x) + .uploadUV(2, GL_FLOAT, sizeof(GlyphVertex), &glyphvertices[info.start].u); + gl.bindTexture2D(info.texture); + gl.drawArrays(GL_QUADS, 0, info.count); + + } + shader->end(); + } + + void TTF::render(const Text& text, int x, int y, int lineheight, int spacing /* = 0 */) + { + render(*text, x, y, lineheight, spacing); + } + + int TTF::getCharWidth(int c) + { + int adw, lsb; + ttf->pushTTFsize(mFontSize); + 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(mFontSize); + 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(mFontSize); + 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(mFontSize); + *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(mFontSize); + GLuint atlas = atlases.back(); + const Color* bitmap = ttf->getCodepointBitmap(character, &w, &h, &xoff, &yoff); + int adw, lsb; + { + /* bake glyph */ + 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.bindTexture2D(atlas); + gl.texSubImage(cursor.x() + xoff, cursor.y() + yoff + baseline, w, h, GL_RGBA, GL_UNSIGNED_BYTE, bitmap); + gl.bindTexture2D(); + 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); + } + + } // namespace Fonts + } // namespace Graphics } // namespace JinEngine #endif // defined(jin_graphics)
\ No newline at end of file diff --git a/src/libjin/graphics/fonts/ttf.h b/src/libjin/graphics/fonts/ttf.h index 8439cd7..5b137ff 100644 --- a/src/libjin/graphics/fonts/ttf.h +++ b/src/libjin/graphics/fonts/ttf.h @@ -19,266 +19,266 @@ namespace JinEngine { - namespace Graphics - { - namespace Fonts - { - - class TTF; - - // - // TTFData - // |- TTF(14px) - // |- TTF(15px) - // . - // . - // . - // - class TTFData : public Object - { - public: - /// - /// - /// - TTFData(const unsigned char* data, unsigned int size); - - /// - /// - /// - ~TTFData(); - - /// - /// - /// - TTF* createTTF(unsigned ttfsize); - - /// - /// - /// - void pushTTFsize(unsigned 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; - - /// - /// - /// - stbtt_fontinfo info; - - /// - /// - /// - struct - { - unsigned char* data; - unsigned int size; - } raw; - - /// - /// - /// - std::vector<float> scales; - - }; - - class TTF : public Font, public Object - { - public: - //static TTF* createTTF(TTFData* ttfData, unsigned ttfSzie); - - /// - /// - /// - Page* typeset(const Text& text, int lineheight, int spacing = 0) override; - - /// - /// - /// - Page* typeset(const Content& text, int lineheight, int spacing = 0) override; - - /// - /// - /// - void render(const Text& text, int x, int y, int lineheight, int spacing = 0) override; - - /// - /// - /// - void render(const Content& text, int x, int y, int lineheight, int spacing = 0) override; - - /// - /// - /// - void render(const Page* page, int x, int y) override; - - /// - /// - /// - ~TTF(); - - private: - - friend class TTFData; - - /// - /// - /// - 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; - - /// - /// - /// - int baseline; - - /// - /// - /// - int descent; - - /// - /// - /// - Math::Vector2<float> cursor; - - }; - - } // namespace Fonts - } // namespace Graphics + namespace Graphics + { + namespace Fonts + { + + class TTF; + + // + // TTFData + // |- TTF(14px) + // |- TTF(15px) + // . + // . + // . + // + class TTFData : public Object + { + public: + /// + /// + /// + TTFData(const unsigned char* data, unsigned int size); + + /// + /// + /// + ~TTFData(); + + /// + /// + /// + TTF* createTTF(unsigned ttfsize); + + /// + /// + /// + void pushTTFsize(unsigned 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; + + /// + /// + /// + stbtt_fontinfo info; + + /// + /// + /// + struct + { + unsigned char* data; + unsigned int size; + } raw; + + /// + /// + /// + std::vector<float> scales; + + }; + + class TTF : public Font, public Object + { + public: + //static TTF* createTTF(TTFData* ttfData, unsigned ttfSzie); + + /// + /// + /// + Page* typeset(const Text& text, int lineheight, int spacing = 0) override; + + /// + /// + /// + Page* typeset(const Content& text, int lineheight, int spacing = 0) override; + + /// + /// + /// + void render(const Text& text, int x, int y, int lineheight, int spacing = 0) override; + + /// + /// + /// + void render(const Content& text, int x, int y, int lineheight, int spacing = 0) override; + + /// + /// + /// + void render(const Page* page, int x, int y) override; + + /// + /// + /// + ~TTF(); + + private: + + friend class TTFData; + + /// + /// + /// + 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; + + /// + /// + /// + int baseline; + + /// + /// + /// + int descent; + + /// + /// + /// + Math::Vector2<float> cursor; + + }; + + } // namespace Fonts + } // namespace Graphics } // namespace JinEngine #endif // defined(jin_graphics) |